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

问题描述 投票:1回答:2

我还有来自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秒。

mysql database collation database-indexes
2个回答
1
投票

使用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不能很好地完成它。


0
投票

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

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

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

但首先,您如何连接以及表定义是什么?

© www.soinside.com 2019 - 2024. All rights reserved.