我还有来自this question的另一个跟进。虽然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
得到了完全相同的explain select count(*) from TransactionApp_transactions where merchantId like binary 'VCARD000%';
输出(rows
的数字略小)
key
列包含两个EXPLAIN
输出的索引名称,但LIKE BINARY
需要26秒,而简单的LIKE
只需2秒。
使用WHERE column LIKE 'value%'
的查询比使用WHERE column LIKE BINARY 'value%'
的column
索引的查询要快得多。这完全是预期的。为什么?
LIKE 'value%'
过滤器使用索引查找匹配的行。它假设要匹配的'value%'
文本使用与列相同的排序规则。并且,索引使用它们索引的列的排序规则;整理被烘焙到索引中。在列包含不区分大小写的文本的情况下,这使得搜索'value%'
,'Value%'
和'VALUE%
都可以使用索引,即使必须在搜索中忽略大小写。
当您使用LIKE BINARY
而不是LIKE
时,您将声明搜索所需的排序规则。您告诉MySQL的查询规划器它不能使用它具有的索引,因为该索引的烘焙排序规则对您的查询没有用。所以它进行全表扫描。那很慢。
如果需要区分大小写的搜索,请在创建(或更改)表时为列声明区分大小写的排序规则。那么LIKE过滤器将区分大小写。
要获得区分大小写的排序规则,您可以创建类似于此的表(您没有显示表定义,因此这是一个猜测)。
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
是名字等的首选)。
但首先,您如何连接以及表定义是什么?