我有疑问,这是我的表格:
mysql> show create table watchdog\G
*************************** 1. row ***************************
Table: watchdog
Create Table: CREATE TABLE `watchdog` (
`index1` int(11) NOT NULL DEFAULT '0',
`index2` int(11) NOT NULL DEFAULT '0',
`dog` int(11) NOT NULL DEFAULT '9',
PRIMARY KEY (`index1`,`index2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
<1> 第一个查询:
select index1, index2
from watchdog
where index1 > 4000008 and index1 < 4200007;
结果:
... | 4200001 | 4200002 | | 4200002 | 4200003 | | 4200003 | 4200004 | | 4200004 | 4200005 | | 4200005 | 4200006 | | 4200006 | 4200007 | +---------+---------+ 199997 rows in set (0.09 sec)
<2> Second query:
select index1, index2
from watchdog
where index2 > 4000009 and index2 < 4200007;
结果:
... | 4200002 | 4200003 | | 4200003 | 4200004 | | 4200004 | 4200005 | | 4200005 | 4200006 | +---------+---------+ 199997 rows in set (1.68 sec)
他们用的时间分别是0.9秒和1.68秒!谁能告诉我为什么?复合键顺序有什么问题?
最佳答案
MySQL 有很好的documentation在复合索引上,您应该查看。让我总结一下您查询的问题。
查询的相关部分是 where
子句:
where index1 > 4000008 and index1 < 4200007;
index2 > 4000009 and index2 < 4200007;
您在 index1, index2
上有一个索引,顺序是这样。通常,MySQL 可以查看查询并使用索引执行以下三项操作之一:
- 决定完全不使用索引(基于统计数据或对查询不适用)
- 决定使用
index1
组件。 - 决定使用
index1
组件和index2
。
在第一个查询中,MySQL可以选择第二个选项。因此,它使用索引进行 index1
比较。然后大概扫描适当的行,查看索引中的 index2
值,找到行 ID,查找它们,然后返回行。
对于第二个where
子句,它不能使用索引。索引的第一个键是 index1
,它不在查询中。因此,MySQL 必须进行全表扫描。
关于复合键中的 MySQL 列顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26255039/