【问题标题】:Why can "WHERE col LIKE 'a%'" use an index, but not "WHERE col LIKE '%a%'"?为什么“WHERE col LIKE 'a%'”可以使用索引,但不能使用“WHERE col LIKE '%a%'”?
【发布时间】:2013-03-07 21:30:42
【问题描述】:

我刚刚发现了这篇文章:

MySQL like query runs extremly slow for 5000 records table

我有兴趣了解 asaph 的帖子,他说:

我不希望 select * from customer 像 '%a%' 这样的代码是 快,因为它不可能使用索引。每条记录都必须 检查。考虑 select * from customer where code like 'a%' if 可能,因为这可以使用索引。

有人能解释一下这两个 select 语句的区别吗?我知道一个人只有一个通配符,只会找到以“a”开头的东西。但是为什么那个可以被索引呢?

【问题讨论】:

  • 我认为这里的问题不是列是否可以被索引,而是索引是否会在特定查询中实际使用

标签: mysql sql indexing


【解决方案1】:

虽然 MySQL 的 B-tree 索引的 actual details 比这更复杂,但对于大多数用途来说,它足以说明在列上创建索引可以让 MySQL 引擎在您的表上执行 SELECTs,就好像它一样由该列订购

如果code 列上有索引,并且您正在搜索code LIKE 'a%' 所在的记录,那么所有MySQL(或任何其他SQL 包,只要它足够聪明)都需要做的就是吐出从“a”开始到“b”开始的所有记录。但是,如果您正在搜索 code LIKE '%a%' 所在的记录,那么已经按 code 排序的表对您没有帮助,因为行是否匹配 WHERE 子句与其在索引中的位置没有简单的关系。所以对于第二个查询,除了检查表中每一行的code 条目的每个字符(除非它已经缓存了结果)之外,数据库无法合理地做任何事情。

这很容易直观地理解,因为您可以想象自己做一些与自己相当相似的事情,作为一个人。如果你想在牛津英语词典中找到所有以'a'开头的单词,那么你只需浏览从'a'开头到'b'开头的所有页面,你看到的都是一个单词以“a”开头。如果您想在字典中的任何位置查找所有带有“a”的单词,那么被排序的字典不会为您提供太多帮助。如果您足够老练,您可以合理地利用字典的顺序一点(例如利用您的知识,字典中第一个 'b...' 单词之前的所有单词都包含一个'a'),但最终你将不得不查看几乎每个单词。

【讨论】:

    【解决方案2】:

    来自manual

    大多数 MySQL 索引(PRIMARY KEYUNIQUEINDEXFULLTEXT)存储在 B 树中。 B 树索引可用于使用 =>>=<<=BETWEEN 运算符的表达式中的列比较。以下SELECT 语句不使用索引:

    SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%';
    

    如果LIKE 的参数是不以通配符开头的常量字符串,则索引也可用于LIKE 比较。例如,以下SELECT statements 使用索引:

    SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%';
    SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%';
    

    【讨论】:

      【解决方案3】:

      MySQL 使用BTREE 索引。

      如果您使用带有 前导 通配符的 LIKE 进行字符串比较,那么 MySQL 执行表扫描会更快,因为索引不能用于缩小结果范围。

      如果您使用带有 尾随 通配符的 LIKE 进行字符串比较,那么使用索引会更快,因为需要扫描的记录更少。

      【讨论】:

        猜你喜欢
        • 2019-09-07
        • 2011-08-20
        • 1970-01-01
        • 2018-11-28
        • 1970-01-01
        • 2012-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多