Базовый запрос MySQL занимает исключительно много времени — план объяснения выглядит довольно хорошо

#mysql #performance #join #coalesce #explain

#mysql #Производительность #Присоединиться #объединить #объясните

Вопрос:

У меня есть запрос с планом объяснения ниже. Он довольно простой, каждое объединение использует индекс (хотя и не уникальный), и это занимает более 5 часов. Самая большая таблица содержит около 100 тыс. записей. Оперативная память и процессор не привязаны или что-то еще, никаких других запущенных запросов, никаких блокировок таблиц. Самая «сложная» часть, которая у меня есть, — это объединение во внешнем соединении. Это меня убивает?

Для пояснения я присоединяюсь к одной и той же таблице дважды, потому что некоторые записи имеют идентификатор пользователя, у некоторых есть только имя / фамилия. Я предпочитаю объединяться с помощью уникального имени пользователя, очевидно, и один из выбранных элементов — coalesce (u1.job_title, u2.job_title)

 from utilization_incident ui

left join users_utilization_v u1
       on  u1.cc_user_id = ui.assigned_to_user_id
       and u1.source_system = ui.source
       and u1.data_date = ui.data_date
left join users_utilization_v u2
       on  u2.first_name = ui.assigned_to_first_name
       and u2.last_name = ui.assigned_to_last_name
       and u2.source_system = ui.source
       and u2.data_date = ui.data_date

left join lkp_job_title_service_area jtsa
       on  jtsa.job_title = coalesce(u1.job_title, u2.job_title)
  

введите описание изображения здесь

Комментарии:

1. просто: попробуйте запустить SQL без coalesce и посмотрите, заметно ли это быстрее

2. Без более глубокого понимания того, как соотносятся данные (и какие точные индексы доступны), трудно дать много советов; но … да, это объединение в качестве условия объединения, вероятно, не приносит вам никакой пользы; вероятно, это приводит к полному сканированию обеих задействованных таблиц. Вероятно, вам лучше использовать два отдельных соединения с этой таблицей (одно с u1, а другое с u2) и решить, какие значения joined jtsa использовать в списке выбора.

3. Кроме того, не все так ясно, что вам нужно присоединиться к users_utilization_v дважды, когда вы могли бы просто объединить условия объединения. OR s редко бывают оптимальными в условиях объединения, но и ненужными объединения не являются.

4. LEFT собирает недостающие строки — вы действительно этого хотите?

Ответ №1:

Возможно, процессор не привязан, но как насчет ввода-вывода?

Сколько оперативной памяти? Какова ценность innodb_buffer_pool_size ?

Пожалуйста, предоставьте SHOW CREATE TABLE .
Пожалуйста, предоставьте весь SELECT .
Пожалуйста, предоставьте текстовую версию EXPLAIN SELECT ... .

В ожидании дальнейших подробностей эти индексы должны помочь:

 users_utilization_v: INDEX(cc_user_id, source_system, data_date)
users_utilization_v: INDEX(first_name, last_name, source_system, data_date)
lkp_job_title_service_area: INDEX(job_title)
  

Удалите LEFT , если вам это не нужно.