Обзор схемы:
- (базовая таблица): ~500 тыс. строк
Код: Выделить всё
Table_A - (таблица поиска 1): ~4,7 млн строк
Код: Выделить всё
Table_B - (таблица поиска 2): ~3,7 млн строк
Код: Выделить всё
Table_C - (данные пользователя): ~50 тыс. строк.
Код: Выделить всё
Table_D
Код: Выделить всё
CREATE VIEW my_slow_view AS
SELECT
a.id,
a.name,
b.number,
b.type,
c.country_name,
c.status,
mgr1.fullname AS primary_manager,
mgr2.fullname AS secondary_manager,
mgr3.fullname AS alternate_manager_1,
mgr4.fullname AS alternate_manager_2,
mgr5.fullname AS alternate_manager_3,
mgr6.fullname AS alternate_manager_4,
mgr7.fullname AS alternate_manager_5
FROM
Table_A a WITH (NOLOCK)
LEFT JOIN Table_B b WITH (NOLOCK)
ON a.id = b.account_fk
AND b.deleted_flag 'Y'
LEFT JOIN Table_C c WITH (NOLOCK)
ON a.id = c.account_fk
AND c.deleted_flag 'Y'
LEFT JOIN Table_D mgr1 WITH (NOLOCK) ON c.manager1_fk = mgr1.user_id
LEFT JOIN Table_D mgr2 WITH (NOLOCK) ON c.manager2_fk = mgr2.user_id
LEFT JOIN Table_D mgr3 WITH (NOLOCK) ON c.manager3_fk = mgr3.user_id
LEFT JOIN Table_D mgr4 WITH (NOLOCK) ON c.manager4_fk = mgr4.user_id
LEFT JOIN Table_D mgr5 WITH (NOLOCK) ON c.manager5_fk = mgr5.user_id
LEFT JOIN Table_D mgr6 WITH (NOLOCK) ON c.manager6_fk = mgr6.user_id
LEFT JOIN Table_D mgr7 WITH (NOLOCK) ON c.manager7_fk = mgr7.user_id
Все объединяемые столбцы имеют соответствующие индексы:
- — КЛАСТЕРНЫЙ индекс
Код: Выделить всё
Table_A.account_id - — НЕКЛАСТЕРИЗИРОВАННЫЙ индекс
Код: Выделить всё
Table_B.account_fk - — НЕКЛАСТЕРИЗИРОВАННЫЙ индекс
Код: Выделить всё
Table_C.account_fk - через менеджер7_fk - отдельные НЕКЛАСТЕРНЫЕ индексы
Код: Выделить всё
Table_C.manager1_fk - - КЛАСТЕРНЫЙ индекс
Код: Выделить всё
Table_D.user_id
Проблема в том, что ОДНА запись в таблице A может иметь:
- Несколько строк в Table_B (например, 10 записей)
- Несколько строк в Table_C (например, 370 записей COUNTRY)
План выполнения показывает:
- Оба индексы используются эффективно (индексный поиск в столбцах соединения).
- Однако предполагаемое количество строк варьируется от 500 тысяч до 27 миллионов и более промежуточных строк.
- 7 последующих объединений в Table_D работают с этими 27 миллионами строк.
- Это просто проблема с бизнес-логикой/проектированием, или мне не хватает какой-то стратегии индексирования?
- Все столбцы объединения имеют индексы. Почему SQL Server по-прежнему работает медленно, если использует поиск по индексу?
- Помогут ли составные индексы на (account_fk, delete_flag), или декартово произведение делает индексацию неактуальной?
- Есть ли подсказки по запросам (HASH JOIN, MERGE JOIN), которые могут помочь, или мне нужно фундаментально реструктурировать представление?
- Добавлены покрывающие индексы → минимальное улучшение
- Использованы подсказки запроса (OPTION (HASH JOIN)) → то же декартово произведение, другой алгоритм соединения
- Проверен план выполнения → подтверждает, что индексы используются, но узким местом является развертывание строк.
Подробнее здесь: https://stackoverflow.com/questions/798 ... timization