|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
Всем здравствуйте! Столкнулся с непонятной для меня проблемой, когда не могу сджойнить пару таблиц. Уже три дня перебираю различные варианты, пока что успеха не достиг. Это повергает в уныние. Оптимизатор по умолчанию выбирает LOOP, но и принудительный перевод в HASH/MERGE не даёт результата даже при ограничении выборки, не говоря уже о полном наборе данных в таблицах :'( Преднастройки:
В кабинетах, работающих по расписанию, производится отпуск услуг. Таблица ServicePointScheduleEveryDay с информацией о рабочих по расписанию интервалах кабинетов на каждый календарный день. Интервалы не пересекаются. Количество строк за всё время 28 206 685. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
Пример данных: Таблица VScheduleItem с информацией об отпусках услуг, можно считать их интервалами занятости. Количество строк за всё время: 3 894 942. Относительно интервалов доступности интервалы занятости могут:
занимать несколько рабочих ячеек кабинета (не обязательно целых) находиться внутри рабочей ячейки Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Пример данных: Задача Для каждого из рабочих интервалов кабинетов на каждый календарный день (ServicePointScheduleEveryDay) определить количество приходящихся интервалов занятости (VScheduleItem). Проблема/предпринимаемые попытки решения Попытка 1. Изначально пытался зачем-то вставлять результат в новую таблицу ServicePointScheduleEDScheduleItemCount, где поля совпадают с таблицей ServicePointScheduleEveryDay, плюс добавляется новое поле ScheduleItemCount. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26.
Напомню, в левой таблице 28 млн строк, в правой таблице - 4 млн. Пытался ограничить в WHERE для одного кабинета (ServicePointId = 5), при таком раскладе в левой таблице 376 852 строк, в правой - 87 832. Дождаться результата выполнения запроса не удаётся. Смена LEFT на INNER (хоть это и не в интересах моей задачи) положительного результата не даёт. По умолчанию оптимизатор выбирает LOOP JOIN и ожидает получить миллиарды записей. Принудительный хинт в MERGE/HASH успеха не дают. В попытках 2 и 3 временно отказался от результата в виде количества приходящихся интервалов занятости, а просто хотел определить был ли занят рабочий интервал или нет: в таблицу ServicePointScheduleEveryDay добавил битовое поле IsBusySegment. Попытка 2. Обновлять ServicePointScheduleEveryDay.IsBusySegment Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Попытка 3. Обновлять ServicePointScheduleEveryDay.IsBusySegment для случаев WHERE EXISTS записи в таблице интервалов занятости. При таком раскладе оптимизатор выбирает LOOP JOIN, повлиять на выбор способа не нашёл. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 00:10 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
pavifed не могу сджойнить пару таблиц ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 09:19 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
invm Расшифруйте Добрый день. Например, код попытки 2, которая уже не отвечает исходной задаче (считает только занятость интервала, а не количество отпускаемых в интервале услуг) не выполняется ни за какое адекватное время (максимум, сколько ждал - 100 минут) при том, что там уже и вместо LEFT JOIN используется INNER и только по одному кабинету ServicePointId = 5. Ожидаемый план запроса получается, на мой взгляд, красивый. В обоих случаях IndexSeek, ожидаемое количество строк корректное. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 09:29 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
pavifed, Проблема именно с update? Если запрос сериализовать во времянку, эффект тот же? Какие блокировки были/есть во время выполнения запроса? С maxdop 1 эффект тот же? упд. Ну и посмотрите загрузку cpu во время выполнения запроса. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 09:34 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
env Проблема именно с update? Не только. SELECT с выводом на экран или в файл также не отрабатывает за адекватное время (результата выполнения я не дождался ни разу, даже при ограничении на 1 кабинет) ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 09:38 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
pavifed, Блокировки проверяли? Может просто одну из таблиц кто-то/что-то блокирует. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 09:45 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
env, спасибо за рекомендации. Попробовал с OPTION (MAXDOP 1). Уже более 10 минут выполняется по 1 кабинету, результат не получен. Блокировки отсутствуют. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 09:57 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
env Если запрос сериализовать во времянку, эффект тот же? Поясните этот момент, пожалуйста. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 09:58 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
pavifed, а вот такая картина изначально была, без OPTION(MAXDOP 1) ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 10:07 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
pavifed, Ваши красивые картинки малоинформативны. Если запрос выполняется "вечно", смотрите его ожидания в sys.dm_waiting_tasks, или в sys.dm_exec_requests. Или установите себе sp_whoisactive ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 10:15 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
invm sys.dm_waiting_tasks ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 10:17 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
invm Или установите себе sp_whoisactive Спасибо, установил, выполнил Код: sql 1.
В поле locks для своего запроса получаю: Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
В поле wait_info - NULL. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 10:38 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
pavifed, авторWHERE для одного кабинета (ServicePointId = 5), при таком раскладе в левой таблице 376 852 строк, в правой - 87 832 Конечно же это не так, предикат ограничивает поиск только в одной из таблиц. Более того, серверу может быть неизвестна корректная оценка кардинальности. Если Вы указали фактические значения, то сравните с теми, которые предоставлены в ожидаемом плане запроса. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 15:07 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
Владислав Колосов, количество строк в ожидаемом плане совпадает с реальным. P.S. ненамеренно оставил запрос работать в фоновой вкладке. По одному кабинету (ServicePointId = 5) запрос отработал за 3 часа 15 минут ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 15:42 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
и что, за 3 часа не могли посмотреть, чего сессия ждет? запустите снова и посмотрите в sys.dm_os_waiting_tasks ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:06 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
pavifed Напомню, в левой таблице 28 млн строк, в правой таблице - 4 млн. Пытался ограничить в WHERE для одного кабинета (ServicePointId = 5), при таком раскладе в левой таблице 376 852 строк, в правой - 87 832. Дождаться результата выполнения запроса не удаётся. Смена LEFT на INNER (хоть это и не в интересах моей задачи) положительного результата не даёт. По умолчанию оптимизатор выбирает LOOP JOIN и ожидает получить миллиарды записей. Принудительный хинт в MERGE/HASH успеха не дают. у меня была вроде аналогичная проблема - в каждой из таблиц было немного строк, а джоин безбожно тупил, в итоге мне пришло в голову, что он пытается мне выдать все комбинации, потому что вы сами говорите, что в один период дат одной таблицы может быть несколько совпадений из другой таблицы, т.е. максимальное кол-во записей, которое потенциально может выдать селект - это 376 852 * 87 832 = ~33 млрд и вот бедный сервер и перелопачивает все комбинации, сверяя попадание периода дат для каждого случая в моем случае, насколько я помню, все в итоге решилось довольно просто, но не помню что я сделал, то ли условие в джоине поменял, то ли структуру БД да и проблема эта была у меня, когда я джоинил не по FK полю, а вот примерно как у вас, периоды дат ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:15 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
pavifed, 1. Если версия позволяет - запустите с live query и посмотрите на реальный план выполнения. 2. merge join по неравенству выглядит несколько странно, покажите план без хинтования ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:23 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
Yasha123, Получаю 129 строк с WITE_TYPE = 'CXPACKET'. Ранее выше писал, что sp_whoisactive возвращает поле wait_info NULL. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:24 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
pavifed, Повторюсь - ваши картинки неинформативны. Не хотите сами разбираться с ожиданиями (предположительно) - тогда запустите запрос еще раз и покажите актуальный план выполнения в формате sqlplan, а не картинкой. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:26 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
т.е. попробуйте связать таблицы ServicePointScheduleEveryDay и VScheduleItem напрямую, например добавив в VScheduleItem поле ServicePointScheduleEveryDayId + FK + индекс по полю ServicePointScheduleEveryDayId ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:27 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
env 2. merge join по неравенству выглядит несколько странно, покажите план без хинтования Без хинтования получаю LOOP в Estimation плане. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:28 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
pavifed Yasha123, Получаю 129 строк с WITE_TYPE = 'CXPACKET'. А какие ожидания с maxdop 1 ? CXPACKET это ожидание связанное с параллелизмом. Например, у вас перекос в распределении данных по потокам. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:28 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
env Если версия позволяет - запустите с live query и посмотрите на реальный план выполнения. invm Повторюсь - ваши картинки неинформативны. Не хотите сами разбираться с ожиданиями (предположительно) - тогда запустите запрос еще раз и покажите актуальный план выполнения в формате sqlplan, а не картинкой. Ок, вернусь к изначальному запросу и попробую выполнить его с live query. Спасибо! ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:30 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
env А какие ожидания с maxdop 1 ? При использовании OPTION (MAXDOP 1) представление sys.dm_os_waiting_tasks возвращает пустой набор. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:33 |
|
Проблема соединения двух таблиц (26 и 4 млн строк)
|
|||
---|---|---|---|
#18+
ну так криво он поделил работу, видите же, что другие thread ждут работающего, которому досталось больше. вам предлагали при maxdop = 1 запускать, попробуйте снова и посмотрим, что там за ожидания, исключим CXPACKET ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 16:35 |
|
|
start [/forum/topic.php?fid=46&msg=40018948&tid=1685404]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
58ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
52ms |
get tp. blocked users: |
1ms |
others: | 311ms |
total: | 458ms |
0 / 0 |