Как Mysql рассматривает сравнение строкового значения с индексированным столбцом varchar? - PullRequest
0 голосов
/ 05 июля 2018

В последнее время я обнаружил проблему с производительностью в следующем случае использования До этого у меня была таблица «MyTable» с индексированным столбцом INT «MyCode» После этого необходимо изменить структуру таблицы, преобразовав столбец «MyCode» в VARCHAR (индекс для столбца был сохранен)

 ALTER TABLE MyTable CHANGE MyCode MyCode VARCHAR(250) DEFAULT NULL

Затем возникла неожиданная задержка, запрос выполнялся как:

 SELECT * FROM MyTable where MyCode = 1234

В этом запросе полностью игнорировалось индексирование MyCode VARCHAR, впечатление было, что оно полностью сканировало таблицу

Преобразование запроса в

 SELECT * FROM MyTable where MyCode = "1234"

Производительность возвращается к оптимальному использованию при индексировании VARCHAR

Итак, вопрос в том ... как это объяснить ... и как на самом деле MySQL относится к индексации. Или, может быть, нужно изменить некоторые настройки БД, чтобы избежать этого?

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Я принял ответ Рика Джеймса, потому что он понял.

Но я бы хотел добавить больше информации после некоторого тестирования.

Случай в вопросе таков: как на самом деле MySQL сравнивает два значения, когда фильтруемый столбец имеет тип varchar, а указанное значение для фильтрации не является строкой. Если это так, вы потеряете возможность использовать индекс, примененный к столбцу VARCHAR, который резко потеряет производительность в вашем запросе, вместо этого он должен быть быстрым и простым.

Объяснение заключается в том, что MySQL перед заданным значением, которое имеет тип, отличный от VARCHAR выполнит полное сканирование таблицы и для каждого поля записи выполнит CAST (varcharcol как предоставленныйvaluetype) и сравнит результат с предоставленным значением.

1009 * Е.Г. *

имеющий столбец VARCHAR с именем "code" и фильтрацией

   SELECT * FROM table WHERE code=1234

будет полностью сканировать каждую запись так же, как и при выполнении

    SELECT * FROM table WHERE CAST(code as UNSIGNED)=1234

Обратите внимание, что если вы протестируете его с 0

  SELECT * FROM table WHERE CAST(code as UNSIGNED)=0

вы получите обратно ВСЕ записи, содержащие строку, для которой значение CAST в UNSIGNED не будет иметь значения без знака для функции mysql CAST.

0 голосов
/ 05 июля 2018
int_col  = 1234      -- no problem; same type
char_col = "1234"    -- no problem; same type
int_col  = "1234"    -- string is converted to number, then no problem
char_col = 1234      -- converting all the strings to numbers -- tedious

В четвертом случае индекс бесполезен, поэтому оптимизатор ищет другой способ выполнения запроса. Это может привести к «полному сканированию таблицы».

Основное исключение включает в себя «индекс покрытия», который работает лишь немного быстрее, - «полный индекс сканирование».

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