MySQL在声明说明中声明使用索引时不使用我的索引

时间:2018-10-23 07:21:40

标签: mysql performance indexing

我最近遇到一个涉及MySQL DBSM的问题。
表格是这样的:

 CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(60) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sex` enum('男','女') DEFAULT NULL,
`amount` float(10,2) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name_i` (`name`),
KEY `sex` (`sex`)
) ENGINE=InnoDB AUTO_INCREMENT=5000001 DEFAULT CHARSET=utf8 

如上所示,我在col name上创建了一个colume索引。
我想在name上执行范围查询,其说明语句为

mysql> explain select * from orders where name like '王%';
+----+-------------+--------+------------+-------+---------------+--------+---------+------+-------+----------+----------------------------------+
| id | select_type | table  | partitions | type  | possible_keys | key    | key_len | ref  | rows  | filtered | Extra                            |
+----+-------------+--------+------------+-------+---------------+--------+---------+------+-------+----------+----------------------------------+
|  1 | SIMPLE      | orders | NULL       | range | name_i        | name_i | 183     | NULL | 20630 |   100.00 | Using index condition; Using MRR |
+----+-------------+--------+------------+-------+---------------+--------+---------+------+-------+----------+----------------------------------+
1 row in set, 1 warning (0.10 sec)

因此它应该使用索引name_i并快速完成查询(我的同学花了0.07秒) 但是,结果是这样的:

| 4998119 | 王缝   |   27 | 男   | 159.21 |
| 4998232 | 王求葬 |   19 | 男   | 335.65 |
| 4998397 | 王倘予 |   49 | 女   | 103.39 |
| 4998482 | 王厚   |   77 | 男   | 960.69 |
| 4998703 | 王啄淋 |   73 | 女   | 458.85 |
| 4999106 | 王般埋 |   70 | 女   | 700.98 |
| 4999359 | 王胆具 |   31 | 女   | 362.83 |
| 4999510 | 王铁脾 |   31 | 女   | 973.09 |
| 4999880 | 王战万 |   59 | 女   | 127.28 |
| 4999928 | 王忆   |   42 | 女   |  72.47 |
+---------+--------+------+------+--------+
11160 rows in set (3.43 sec)

它似乎根本不使用索引,因为数据是通过主键id而不是col name排序的(除了速度太慢,与0.07秒相比)。 / p>

有人也遇到过这个问题吗?

1 个答案:

答案 0 :(得分:1)

  • “国王”(Kings)占表的百分比?如果大于20%,它将选择执行表扫描而不是使用索引。 (这实际上可能会更快。)(基于注释,表的0.22%是Kings。)
  • EXPLAIN和查询的执行是分开的。尽管我不记得要证明这一点,但EXPLAIN可能会说一句话,但查询将以另一种方式起作用。
  • 表中是否有500万行?第一次运行时缓存是否“冷”?而且它必须从磁盘获取11,160行?然后第二次,所有内容都在缓存中,那么快吗?
  • 该表是否以“字母顺序”(或任何中文单词)顺序加载?如果是这样,ids 的名称很有可能以相同的顺序排列吗?
  • 您显然正在使用utf8_general_ci COLLATION也许它对中文的排序不太好。 (提供一个测试用例;我将做一些测试。)
  • 我不明白为什么它提到了MRR
  • 我也为“ 1分32.24秒”感到困惑。 ORDER BY name应该进一步鼓励优化器使用INDEX(name)。您可以打开“优化程序跟踪”吗?

要真正查看它是否使用了索引,请执行以下操作:

FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler%';

如果大数字看起来像表中的行数,那么它将进行表扫描。如果它们看起来更像11160,则使用索引。