为什么 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''
一个功能发挥作用。索引不会被使用。
尝试了 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
=
,>
,>=
,<
,<=
, orBETWEEN
operators. The index also can be used forLIKE
comparisons if the argument toLIKE
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''
一个功能发挥作用。索引不会被使用。