col LIKE BINARY 'val%' 比 col LIKE 'val%' 慢得多。为什么?

col LIKE BINARY 'val%' much slower than col LIKE 'val%' . Why?

我有另一个来自 的跟进。尽管 LIKE 模式搜索(由于归类集)使用索引并且比 LIKE BINARY 快得多,但对两个查询进行解释似乎表明两个查询都使用索引。

explain select count(*) from TransactionApp_transactions where merchantId like 'VCARD000%'

| id | select_type | table                       | type  | possible_keys                        | key                                 | key_len | ref  | rows     | Extra                    |
+----+-------------+-----------------------------+-------+--------------------------------------+--------------------------------------+---------+------+----------+--------------------------+
|  1 | SIMPLE      | TransactionApp_transactions | range | TransactionApp_transactions_fc3e7169 | TransactionApp_transactions_fc3e7169 | 767     | NULL | 12906834 | Using where; Using index |

我得到了 explain select count(*) from TransactionApp_transactions where merchantId like binary 'VCARD000%'; 完全相同的 EXPLAIN 输出(rows 的数字稍小)

key 列包含两个 EXPLAIN 输出的索引名称,但是 LIKE BINARY 需要 26 秒,而简单的 LIKE 只需要 2 秒。

给定 column 上的索引,使用 WHERE column LIKE 'value%' 的查询比使用 WHERE column LIKE BINARY 'value%' 的查询快得多。这完全是预料之中的。为什么?

LIKE 'value%' 过滤器使用索引来查找匹配的行。它假定要匹配的 'value%' 文本使用与列相同的排序规则。而且,索引使用它们索引的列的排序规则;排序规则被烘焙到索引中。在列包含不区分大小写的文本的情况下,这使得搜索 'value%''Value%''VALUE%' 都可以使用索引,即使必须忽略大小写搜索。

当您使用 LIKE BINARY 而不是 LIKE 时,您声明了搜索所需的排序规则。您告诉 MySQL 的查询计划器它不能使用它拥有的索引,因为该索引的内置排序规则对您的查询没有用。所以它会进行完整的 table 扫描。就是慢。

如果您需要区分大小写的搜索,请在创建(或更改)table 时为列声明区分大小写的排序规则。然后 LIKE 过滤器将区分大小写。

要获得区分大小写的排序规则,您可以创建这样的 table(您没有显示您的 table 定义,所以这是一个猜测)。

  CREATE TABLE tbl (
     ...
     mid VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_bin,
     ...
  )

或者您可以像这样更改列以具有区分大小写的排序规则。

 ALTER TABLE tbl MODIFY mid VARCHAR(255) COLLATE latin1_bin;

备注:WHERE col LIKE BINARY 'value%'是一种奇怪的查询方式。这可能就是为什么 EXPLAIN 不能很好地处理它的原因。

对所有这些使用相同排序规则:

  • 正在连接到数据库
  • 客户端字节数
  • 正在测试的列。

可能 merchantId 是(或_应该是)CHARACTER SET ascii。这可能与其他字符串不一致(utf8mb4 是名称等的首选)。

但首先,您是如何连接的,table 定义是什么?