【问题标题】:Why sql "column like 'pattern%'" doesn't use the index? [duplicate]为什么 sql "column like 'pattern%'" 不使用索引? [复制]
【发布时间】:2020-03-12 00:51:52
【问题描述】:

尝试了 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'”不会。
但是在 1st 条件下,它并没有像我想的那样成功。是因为 create_time 的列类型是 DATETIME 吗?
而且我在官方参考手册中与索引交互时找不到有关所有这些“喜欢”SQL 差异的详细信息。
有人可以与我分享官方链接吗?(我得到的只是传闻)

【问题讨论】:

标签: mysql date query-optimization where-clause sql-like


【解决方案1】:

考虑this part of the documentation

B 树索引可用于使用 =>>=<<=BETWEEN 运算符的表达式中的列比较。如果LIKE 的参数是不以通配符开头的常量字符串,则该索引也可用于LIKE 比较。

旁注:正如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''

一个函数开始起作用了。不会使用索引。

【讨论】:

  • "您正在将日期与字符串进行比较。这需要 MySQL 转换数据。因为隐含地,一个函数发挥作用,因此此处不会使用索引。如果 create_time 是一个字符串,将使用索引。” 实际上create_time like '2019-10%' 可以使用索引,但它将是一个完整的索引扫描.. -> db-fiddle.com/f/rrTcypcsqrKLV7jBC7P7gQ/3
  • @RaymondNijland:是的,你是对的(实际上 OP 发布了与你相同的解释)。我更新了我的答案,谢谢!
  • date_format 也是如此 -> db-fiddle.com/f/rrTcypcsqrKLV7jBC7P7gQ/5 也可以进行索引扫描..
  • 但总的来说,您确实希望使 create_time between '2019-10-01 00:00:00' and '2019-10-31 23:59:59' 的搜索条件 "sargable" 可以更好地使用索引..
猜你喜欢
  • 1970-01-01
  • 2015-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
  • 2011-10-05
  • 1970-01-01
  • 2021-03-20
相关资源
最近更新 更多