mySQL查询优化(RANGE)

时间:2014-02-14 02:54:04

标签: mysql

好的,所以查询很简单。这是它存储在的表中:

CREATE TABLE `ips` (
  `ip` int(11) unsigned NOT NULL DEFAULT '0',
  `ip_start` int(11) unsigned NOT NULL DEFAULT '0',
  `ip_end` int(11) unsigned NOT NULL DEFAULT '0',
  KEY `IP` (`ip`),
  KEY `IP_RANGE_END` (`ip_end`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

此表填充了单个IP(在IP列中)或IP范围(ip_start到ip_end)。

以下是我正在使用的功能:

CREATE DEFINER=`root`@`%` FUNCTION `in_adometry`(in_ip VARCHAR(30)) RETURNS int(11)
    DETERMINISTIC
BEGIN

SET @ip = 0;

SELECT COUNT(*) INTO @ip FROM ips WHERE (INET_ATON(in_ip) BETWEEN ip_start AND ip_end) OR  ip = INET_ATON(in_ip) LIMIT 1;

IF @ip > 0  THEN
    RETURN 1;
END IF;

RETURN 0;
END

我目前在亚马逊的RDS(中等大小)上托管这个,在CPU达到100%以上之前,我不能再每秒获得800次查询。此RDS中没​​有其他内容,但只有一个表。有110万个单一IP,其次是大约3,000个IP范围(共有超过2000万个IP)。我该怎么做才能加快速度呢?

2 个答案:

答案 0 :(得分:1)

执行count(*)可能是不必要的。试试这个:

BEGIN
IF exists (SELECT 1
           FROM ips
           WHERE INET_ATON(in_ip) BETWEEN ip_start AND ip_end OR ip = INET_ATON(in_ip)
          )
THEN
    RETURN 1;
END IF;

RETURN 0;

答案 1 :(得分:0)

查询速度慢的一个可能原因是(来自MySQL文档):

  

对于使用MEMORY存储引擎的表,如果运行检查值范围的查询(使用索引列上的>,< =或BETWEEN等运算符),请使用USING BTREE子句创建索引。默认(USING HASH)对于使用相等运算符(=或< =>)检索单个行很快,但速度要慢得多(需要全表扫描)来检查一系列列值。使用USING BTREE子句创建的MEMORY表仍然可以快速进行相等比较,因此请将该子句用于处理各种查询的MEMORY表。

更改索引类型可以显着加快查询速度。有关详细信息,请阅读Avoid Full Table Scan