在MySQL中使用索引

时间:2013-10-18 07:40:08

标签: mysql

奇怪的事情发生了。任何人都可以解释。 我有一张桌子。

CREATE TABLE "country_ip" (
  "begin_ip" varchar(15) NOT NULL,
  "end_ip" varchar(15) NOT NULL,
  "begin_ip_long" int(10) unsigned NOT NULL,
  "end_ip_long" int(10) unsigned NOT NULL,
  "id" char(2) NOT NULL,
  "label" varchar(50) NOT NULL,
  KEY "begin_ip_long" ("begin_ip_long","end_ip_long"),
  KEY "end_ip_long" ("end_ip_long")
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

大约有15万条记录。 下一个查询有很大的时差

0.06329400 | SELECT * FROM `country_ip` WHERE '1405662435' BETWEEN `begin_ip_long` AND `end_ip_long` LIMIT 1
0.06214600 | SELECT * FROM `country_ip` USE INDEX (begin_ip_long, end_ip_long) WHERE 1405662435 BETWEEN `begin_ip_long` AND `end_ip_long` LIMIT 1
0.00008400 | SELECT * FROM `country_ip` USE INDEX (end_ip_long) WHERE 1405662435 BETWEEN `begin_ip_long` AND `end_ip_long` LIMIT 1

任何人都可以解释为什么会发生这种情况?我的意思是为什么只有 USE INDEX(end_ip_long)有助于使用 USE INDEX(begin_ip_long) USE INDEX(begin_ip_long,end_ip_long)无效。感谢。

2 个答案:

答案 0 :(得分:1)

也许是因为索引(end_ip_long)小于(begin_ip_long, end_ip_long),它适合内存,一列足够有选择性。虽然较大的索引可能需要从磁盘读取。

答案 1 :(得分:1)

由于您可以让单列(END_IP_LONG)索引快速运行,为什么不只是索引&在一列上搜索?

我可能会使用BEGIN_IP_LONG并搜索指定IP为> = country.BEGIN_IP_LONG的第一条记录,按IP降序排序,限制1.这应该检索“floor”条目,您需要做的就是检查指定的IP是否超出该国家/地区的END_IP_LONG。

这将仅使用单列索引正确完成查找。 (所有这些都假定范围不重叠,我认为假设你的结构是正确的。)


正如其他人所建议的那样,调查MySQL的计划(可能还有重建统计数据)是值得的 - 但从技术上讲,非重叠范围查找在技术上应该只能在一个边界上使用索引。