присоединение к маленькому столу значительно замедляет запрос

Проблема. Объединение относительно небольшой таблицы в запрос со многими объединениями удваивает время выполнения запроса.

Задача: как оптимизировать структуру запросов или данных, чтобы запрос выполнялся намного быстрее?

Есть индексы повсюду, и статистика актуальна.

3 прохода, измеренные с помощью SQL Server Profiler:

  • Без дополнительного подключения : avg 3741ms
  • С дополнительным соединением: avg 6733ms – это + 80%

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

  • budget таблицы содержит около 700 000 записей
  • Для фильтрации мы имеем таблицы f1 , f2 , f3 которые содержат значения, выбранные пользователем. Эти таблицы фильтров имеют от 1 до макс. 70 записей
  • Для агрегирования мы имеем таблицы a1 , a2 , a3 которые используются для агрегирования измерений для группирования агрегатов.

  • Таблица бюджета: 700 000 записей

  • Итоговый результат: 2,400 записей

Исходный запрос:

 select a1.agg1, a2.agg2, a3.agg3, sum(b.value) from budget b -- 700.000 records inner join f1 on b.dim1 = f1.dim1 inner join f2 on b.dim2 = f2.dim2 inner join f3 on b.dim3 = f3.dim3 inner join a1 on b.dim1 = a1.dim1 inner join a2 on b.dim2 = a2.dim2 inner join a3 on b.dim3 = a3.dim3 group by a1.agg1, a2.agg2, a3.agg3 order by a1.agg1, a2.agg2, a3.agg3 

Теперь я добавляю левое соединение. Это приводит к дополнительному подсчету дополнительной таблицы, которая содержит комментарии к некоторым цифрам.

Таким образом, это объединение добавляет столбец в результат, но не меняет строки.

В comments таблице всего около 1500 записей.

Новый запрос:

 select a1.agg1, a2.agg2, a3.agg3, sum(b.value), count(c.CommentText) as commentcount from budget b -- 700.000 records inner join f1 on b.dim1 = f1.dim1 inner join f2 on b.dim2 = f2.dim2 inner join f3 on b.dim3 = f3.dim3 inner join a1 on b.dim1 = a1.dim1 inner join a2 on b.dim2 = a2.dim2 inner join a3 on b.dim3 = a3.dim3 left join comments c on b.dim1= c.dim1 and b.dim2=c.dim2 and b.dim3=c.dim3 group by a1.agg1, a2.agg2, a3.agg3 order by a1.agg1, a2.agg2, a3.agg3 

Я подробно описал планы выполнения обоих запросов. Дополнительное левое соединение приводит к 3 дополнительным операциям со следующими расходами:

  • Сканирование кластерного индекса (на объединенной таблице): 1%
  • Merge Join (левое внешнее соединение): 10%
  • Сортировать: 13%

Сортировка – это дополнительный вид, который появляется только при соединении. С дополнительным соединением у меня есть два вида (один до и один после объединения слияния), иначе только один вид.

Интересно, что затраты не соответствуют действительности. Но в любом случае. Основной вопрос: как это можно улучшить? Есть идеи?

Давайте будем гением компьютера.