为什么 sql "column like 'pattern%'" 不使用索引?

Why sql "column like 'pattern%'" doesn't use the index?

尝试了 3 种不同的方法。

第一

explain select * from test where create_time like '2019-10%';
id|select_type|table|partitions|type|possible_keys       |key|key_len|ref|rows |filtered|Extra      |
--|-----------|-----|----------|----|--------------------|---|-------|---|-----|--------|-----------|
 1|SIMPLE     |test |          |ALL |test_create_time_IDX|   |       |   |10376|   11.11|Using where|

第二

explain select * from test where create_time between '2019-10-01 00:00:00' and '2019-10-31 23:59:59';
id|select_type|table|partitions|type |possible_keys       |key                 |key_len|ref|rows|filtered|Extra                |
--|-----------|-----|----------|-----|--------------------|--------------------|-------|---|----|--------|---------------------|
 1|SIMPLE     |test |          |range|test_create_time_IDX|test_create_time_IDX|6      |   |   5|     100|Using index condition|

第三

explain select * from test where date_format(create_time,'%Y-%m') = '2019-10';
id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows |filtered|Extra      |
--|-----------|-----|----------|----|-------------|---|-------|---|-----|--------|-----------|
 1|SIMPLE     |test |          |ALL |             |   |       |   |10376|     100|Using where|

有人告诉我 "like 'pattern%'" 会使用索引。"like '%pattern%'"、"like '%pattern'" 不会。
但是在第一个条件下它并没有像我想的那样工作。是因为create_time的列类型是DATETIME吗?
在与官方参考手册中的索引交互时,我找不到有关所有这些 "like" SQL 的差异的详细信息。
谁能分享一个官方的link给我吗?(我得到的都是道听途说)

考虑 this part of the documentation:

A B-tree index can be used for column comparisons in expressions that use the =, >, >=, <, <=, or BETWEEN operators. The index also can be used for LIKE comparisons if the argument to LIKE is a constant string that does not start with a wildcard character.

旁注:因为 documented here 大多数 MySQL 索引(PRIMARY KEY、UNIQUE、INDEX 和 FULLTEXT)存储在 B 树中


在你的例子中:

create_time like '2019-10%'

您正在将日期与字符串进行比较。这需要MySQL 来转换数据。正如您在 explain 的输出中看到的那样,可以使用索引,但它将是全索引扫描。如果 create_time 是一个字符串,索引将与范围扫描一起使用(效率更高)。

create_time between '2019-10-01 00:00:00' and '2019-10-31 23:59:59'

between允许MySQL优化索引的使用(范围扫描)。

date_format(create_time,'%Y-%m') = '2019-10''

一个功能发挥作用。索引不会被使用。