好的,所以查询很简单。这是它存储在的表中:
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)。我该怎么做才能加快速度呢?
答案 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。