MySQL:在这个例子中使用例程来查找匹配不是应该更快吗?

标签 mysql sql-optimization maxmind table-index

执行此查询需要0.0002秒:

SELECT country,city
FROM location
WHERE locID = 30296
LIMIT 1

locID 显然是一个 INDEX。

此另一个查询使用 routine ,并需要0.0005秒执行(返回30296):

SELECT IPTOLOCID(
'190.131.60.58'
)

那么,为什么这个组合查询需要1.7912秒来执行?看起来比应有的要多:

SELECT country, city
FROM location
WHERE locID = IPTOLOCID('190.131.60.58')
LIMIT 1

以防万一您发现这很有用,这些是表格和例程:

CREATE TABLE  `blocks` (
  `startIPNum` int(10) unsigned NOT NULL,
  `endIPNum` int(10) unsigned NOT NULL,
  `locID` int(10) unsigned NOT NULL,
  PRIMARY KEY  (`startIPNum`,`endIPNum`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=1 DELAY_KEY_WRITE=1;

CREATE TABLE  `location` (
  `locID` int(10) unsigned NOT NULL,
  `country` char(2) default NULL,
  `region` char(2) default NULL,
  `city` varchar(45) default NULL,
  `postalCode` char(7) default NULL,
  `latitude` double default NULL,
  `longitude` double default NULL,
  `dmaCode` char(3) default NULL,
  `areaCode` char(3) default NULL,
  PRIMARY KEY  (`locID`),
  KEY `Index_Country` (`country`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED;

DELIMITER $$

DROP FUNCTION IF EXISTS `IPTOLOCID` $$
CREATE FUNCTION `IPTOLOCID`( ip VARCHAR(15)) RETURNS int(10) unsigned
BEGIN
  DECLARE ipn INTEGER UNSIGNED;
  DECLARE locID_var INTEGER;
  IF ip LIKE '192.168.%' OR ip LIKE '10.%' THEN
    RETURN 0;
  END IF;
  SET ipn = INET_ATON(ip);
  SELECT locID INTO locID_var
    FROM `blocks`
    INNER JOIN
      (SELECT MAX(startIPNum) AS start
       FROM `blocks`
       WHERE startIPNum <= ipn) AS s
    ON (startIPNum = s.start)
    WHERE endIPNum >= ipn;
  RETURN locID_var;
END $$

DELIMITER ;

最佳答案

我不知道为什么之前的答案被否决了,但他/她是对的。该函数针对 location 中的每一行执行。表因为:

  • [NOT] DETERMINISTIC函数定义中提供了子句,因此 NOT DETERMINISTIC 假设
  • LIMIT子句在该过程的最后应用,此时所有行都已被扫描,并且 WHERE已检查每个人的状况

如果优化器决定不使用索引,我也不会感到惊讶,因为所有行最终都会被扫描。您可以使用 EXPLAIN 进行检查。

如果您将函数重新定义为 DETERMINISTIC ,还添加 READS SQL DATA以避免任何意外的条款。

顺便说一句,就其结果而言,这个函数毫无意义。这应该作为 View 来实现(这样问题就不会出现)。

关于MySQL:在这个例子中使用例程来查找匹配不是应该更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17355266/

相关文章:

php - 将php日期转换为mysql格式

sql - 存储过程非常慢

mysql - MySQL InnoDB 采用的执行计划效率不高

php - 我如何在 php 中使用 MaxMind 的数据库

java - MaxMind 从 IP 地址获取 Lat/Lng,InvalidDatabaseException 错误

geoip - 如何下载 GeoLite2-Country.mmdb.gz 现在需要添加访问代码

mysql - 将多个 select 语句结果存储到一个变量中

mysql - 什么时候查询结果是非标量的?

mysql - 如何正确分组和排序

sql - 使用内部连接和排序依据优化 sql 查询