【问题标题】:Why is MySQL not using composite key in range query?为什么 MySQL 不在范围查询中使用复合键?
【发布时间】:2012-12-11 11:06:24
【问题描述】:

我检查了许多其他 SO 帖子和 MySQL 文档,但似乎无法得到关于为什么不使用索引以及如何强制使用它的答案 - 我可以看到许多其他人也有类似的情况问题,但找不到解决办法。

表格是这样的

CREATE TABLE `countries_ip` (
`ipfrom` INT(10) UNSIGNED ZEROFILL NOT NULL,
`ipto` INT(10) UNSIGNED ZEROFILL NOT NULL,
`countrySHORT` CHAR(2) NULL DEFAULT NULL,
`country_id` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`ipfrom`, `ipto`, `country_id`),
INDEX `from_to_index` (`ipfrom`, `ipto`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

不知道为什么“from_to_index”在那里——对我来说似乎是多余的。但无论如何,EXPLAIN 查询看起来像这样

EXPLAIN SELECT *
        FROM track_report t, countries_ip ip
        WHERE t.ip BETWEEN ip.ipfrom AND ip.ipto

EXPLAIN 的结果如下:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  t   ALL getwebmaster    NULL    NULL    NULL    36291   
1   SIMPLE  ip  ALL PRIMARY,from_to_index   NULL    NULL    NULL    153914  Range checked for each record (index map: 0x3)

如您所见,countries_ip 表中的 PRIMARY KEY 未使用,因此查询需要很长时间(countries_ip 有超过 150k 条记录)

我可能遗漏了一些简单的东西,但是对于如何优化此查询的任何建议都将不胜感激。提前致谢。

【问题讨论】:

  • 您是否尝试过使用显式连接?
  • 连接条件是范围限制的,会导致全表扫描,可以使用逻辑运算符代替between
  • @juergen - 遗憾的是使用 INNER JOIN 没有任何区别,不幸的是,Sashi 也没有使用逻辑运算符!

标签: mysql composite-key composite-primary-key


【解决方案1】:

可能有助于在track_report.ip 上定义索引。见SQL Fiddle

我修改了 where 子句来进行显式比较,现在它使用 from_to_index。

SELECT ip
FROM track_report t, countries_ip ip
where t.ip >= ip.ipfrom and t.ip <= ip.ipto

SQL Fiddle

【讨论】:

  • 嗨,Olaf,track_report 上已经有一个索引 - getwebmaster 是一个复合键,其中 ip 是第一个字段
  • @pavsid 根据你的解释它没有被使用,而在 SQL Fiddle 它使用单列索引,我定义了。
  • 是的,但这可能取决于我的解释中的优化器。即使我专门为ip 字段添加索引,该索引也不会被使用(可能是由于表的大小?)
  • @pavsid 我玩了一会儿,现在它使用复合索引。查看修改后的答案。
  • 当表格有数据时它仍然不使用索引 - 上面的 Sashi 建议但不起作用。即使我添加USE INDEX (PRIMARY),索引也不会被使用
猜你喜欢
  • 2017-03-05
  • 2015-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-24
  • 2020-06-25
  • 2022-12-12
  • 1970-01-01
相关资源
最近更新 更多