2013-07-24 1 views
4

Итак, я запустил следующее в консоли MySQL в качестве контрольного теста, чтобы увидеть, что сдерживало скорость моего запроса.MySQL CAST уверен, берет свое сладкое время

SELECT bbva_deductions.ded_code, SUBSTRING_INDEX(bbva_deductions.employee_id, '-' , -1) AS tt_emplid, 
      bbva_job.paygroup, bbva_job.file_nbr, bbva_deductions.ded_amount 
      FROM bbva_deductions 
      LEFT JOIN bbva_job 
      ON CAST(SUBSTRING_INDEX(bbva_deductions.employee_id, '-' , -1) AS UNSIGNED) = bbva_job.emplid LIMIT 500 

Для обеспечения безопасности потребовалось приблизительно 4 секунды. (кажется очень высоким только для 500 строк).

Просто удаление CAST часть соединения снизилось, что 0,01 секунд ...

Почему на земле Mr.CAST так медленно? Я что-то делаю, чтобы разозлить богов MySQL здесь?

Edit:

В соответствии с просьбой вот EXPLAIN выход:

enter image description here

И без CAST:

enter image description here

EXPLAIN EXTENDED:

enter image description here

+0

Результаты опубликованы –

+0

Опубликован новый вывод –

+0

Я просто попытался это сделать, и он смог использовать индексный поиск просто отлично. (имеет смысл, потому что это просто поле SELECT, а не часть ключа). Я также попробовал EXPLAIN EXTENDED по запросу при использовании CAST() и получил следующее сообщение: Невозможно использовать ref доступ к индексу 'emplid' из-за преобразования типа или сортировки в поле 'emplid' –

ответ

6

Как указано под How MySQL Uses Indexes:

MySQL использует индексы для этих операций:

[ deletia ]
  • Для извлечения строк из других таблиц при выполнении объединений. MySQL может более эффективно использовать индексы в столбцах, если они объявлены как один и тот же тип и размер. В этом контексте VARCHAR и CHAR считаются одинаковыми, если они объявлены как одинаковые. Например, VARCHAR(10) и CHAR(10) имеют одинаковый размер, но VARCHAR(10) и CHAR(15) - нет.

    Сравнение разнородных столбцов может препятствовать использованию индексов, если значения не могут сравниваться напрямую без преобразования. Предположим, что числовой столбец сравнивается со столбцом строки. Для заданного значения, такого как 1 в числовой колонке, оно может сравниваться с любым количеством значений в столбце строки, например '1', ' 1', '00001' или '01.e1'. Это исключает использование любых индексов для столбца строки.

В вашем случае, вы пытаетесь присоединиться на сравнении подстроки (столбец строки в одной таблице) и столбец строки в другой таблице. Индекс может использоваться для этой операции, однако сравнение выполняется лексикографически (т. Е. Обработка операндов как строк, даже если они представляют числа).

Явным образом отбрасывая одну сторону целому числу, сравнение выполняется численно (по желанию), но для этого требуется, чтобы MySQL был implicitly convert the type столбца строки и, следовательно, он не смог использовать индекс этого столбца.

Вы попали в этот дорожный альбом, потому что ваша схема плохо разработана.Вы должны стремиться к тому, чтобы все столбцы:

  1. кодируются с использованием типов данных, наиболее важных для их содержимого; и

  2. содержат только одну часть информации — см Is storing a delimited list in a database column really that bad?

В крайней мере, ваш bbva_job.emplid должен быть целым числом; и ваш bbva_deductions.employee_id должен быть разделен так, чтобы его части хранились в отдельных (соответствующих строках) столбцах. С соответствующими индексами ваш запрос будет значительно более результативным.

+0

+1 Хороший ответ. – peterm