col LIKE BINARY 'val%' намного медленнее, чем col LIKE 'val%'. Зачем? - PullRequest
1 голос
/ 17 апреля 2019

У меня есть еще одно продолжение от этого вопроса . Хотя поиск по шаблону 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 секунды.

Ответы [ 2 ]

1 голос
/ 17 апреля 2019

Запрос с использованием WHERE column LIKE 'value%' выполняется намного быстрее, чем запрос с использованием WHERE column LIKE BINARY 'value%' с указанным индексом column.Это вполне ожидаемо.Почему?

Фильтр LIKE 'value%' использует индекс для поиска совпадающих строк.Предполагается, что для текста 'value%' для сопоставления используется то же сопоставление, что и для столбца.И индексы используют параметры сортировки столбцов, которые они индексируют;сопоставление запекается в индексе.В сценарии, где столбец содержит регистрозависимый текст, это позволяет выполнять поиск для 'value%', 'Value%' и 'VALUE% 'all, чтобы использовать индекс, даже если регистр должен игнорироваться.

Когда вы используете 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 голосов
/ 24 апреля 2019

Используйте одинаковое сопоставление для всех этих:

  • подключение к базе данных
  • байтов в клиенте
  • столбец, являющийсяпроверено.

Вероятно merchantId есть (или _ должно быть) CHARACTER SET ascii.Это может противоречить другим строкам (utf8mb4 предпочтительнее для имен и т. Д.).

Но сначала, как вы подключаетесь и каково определение таблицы?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...