我在一张表中有超过170万条记录,其中包含主要密钥和相应详细信息的IP地址范围(开始和结束)。
表结构是
mysql> desc csv;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| begin | bigint(20) | NO | PRI | 0 | |
| end | bigint(20) | NO | PRI | 0 | |
| code | char(2) | YES | | NULL | |
| country | varchar(50) | YES | | NULL | |
| city | varchar(50) | YES | | NULL | |
| area | varchar(50) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
由于主键中的索引,当要像这样进行完全匹配时搜索速度很快
mysql> SELECT * FROM csv WHERE begin=3338456576;
+------------+------------+------+---------------+----------+---------------+
| begin | end | code | country | city | area |
+------------+------------+------+---------------+----------+---------------+
| 3338456576 | 3338456831 | US | UNITED STATES | NEW YORK | NEW YORK CITY |
+------------+------------+------+---------------+----------+---------------+
1 row in set (0.03 sec)
但是当我尝试在一个范围内搜索时,需要更长的时间。
mysql> SELECT * FROM csv WHERE begin<3338456592 AND end>3338456592;
+------------+------------+------+---------------+----------+---------------+
| begin | end | code | country | city | area |
+------------+------------+------+---------------+----------+---------------+
| 3338456576 | 3338456831 | US | UNITED STATES | NEW YORK | NEW YORK CITY |
+------------+------------+------+---------------+----------+---------------+
1 row in set (1.59 sec)
有什么方法可以优化我的查询来搜索某个范围内的IP地址吗?
修改
创建表语句
CREATE TABLE `csv` (
`begin` bigint(20) NOT NULL DEFAULT '0',
`end` bigint(20) NOT NULL DEFAULT '0',
`code` char(2) DEFAULT NULL,
`country` varchar(50) DEFAULT NULL,
`city` varchar(50) DEFAULT NULL,
`area` varchar(50) DEFAULT NULL,
PRIMARY KEY (`begin`,`end`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
答案 0 :(得分:3)
如果IP范围不重叠,那么查询永远不会返回超过1行,您可以使用:
SELECT q.*
FROM
( SELECT csv.*
FROM csv
WHERE csv.begin < 3338456592
ORDER BY csv.begin DESC
LIMIT 1
) AS q
WHERE 3338456592 < q.end ;
不需要添加索引。将使用主索引。
答案 1 :(得分:1)
如果范围重叠,您应该:
答案 2 :(得分:0)
SELECT begin, end, code, country, city, area FROM csv WHERE begin <> 3338456592 HAVING begin NOT BETWEEN MIN(begin) AND MAX(end)
得分是什么?
<强> UPD 强>: 这是我的表结构版本。
CREATE TABLE `csv` (
`begin` INT(10) NOT NULL DEFAULT '0',
`end` INT(10) NOT NULL DEFAULT '0',
`code` char(2) DEFAULT NULL,
`country` varchar(50) DEFAULT NULL,
`city` varchar(45) DEFAULT NULL,
`area` varchar(40) DEFAULT NULL,
KEY `combined` (`begin`,`end`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
我认为使用国家和代码作为ENUM它更快。