У меня есть представление в SQL Server, выполнение которого занимает более 120 минут, и я пытаюсь понять, является ли это проблемой индексации или фундаментальной проблемой проектирования. Обзор схемы:
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
Текущее покрытие индекса:
Все объединяемые столбцы имеют соответствующие индексы:
Проблема:
Проблема в том, что ОДНА запись в таблице A может иметь:
Несколько строк в Table_B (например, 10 записей)
Несколько строк в Table_C (например, 370 записей COUNTRY)
Это создает декартово произведение: 10 × 370 = 3700 строк на каждую запись в таблице A, которое затем присоединяется к Table_D семь раз для поиска менеджера. План выполнения показывает:
Оба индексы используются эффективно (индексный поиск в столбцах соединения).
Однако предполагаемое количество строк варьируется от 500 тысяч до 27 миллионов и более промежуточных строк.
7 последующих объединений в Table_D работают с этими 27 миллионами строк.
Вопросы:
Это просто проблема с бизнес-логикой/проектированием, или мне не хватает какой-то стратегии индексирования?
Все столбцы объединения имеют индексы. Почему SQL Server по-прежнему работает медленно, если использует поиск по индексу?
Помогут ли составные индексы на (account_fk, delete_flag), или декартово произведение делает индексацию неактуальной?
Есть ли подсказки по запросам (HASH JOIN, MERGE JOIN), которые могут помочь, или мне нужно фундаментально реструктурировать представление?
У меня есть представление в SQL Server, выполнение которого занимает более 120 минут, и я пытаюсь понять, является ли это проблемой индексации или фундаментальной проблемой проектирования. [b]Обзор схемы:[/b] [list] [*][code]Table_A[/code] (базовая таблица): ~500 тыс. строк [*][code]Table_B[/code] (таблица поиска 1): ~4,7 млн строк [*][code]Table_C[/code] (таблица поиска 2): ~3,7 млн строк [*][code]Table_D[/code] (данные пользователя): ~50 тыс. строк. [/list] [b]Структура просмотра (упрощенная):[/b] [code]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 [/code] [b]Текущее покрытие индекса:[/b] Все объединяемые столбцы имеют соответствующие индексы: [list] [*][code]Table_A.account_id[/code] — КЛАСТЕРНЫЙ индекс ✅ [*][code]Table_B.account_fk[/code] — НЕКЛАСТЕРИЗИРОВАННЫЙ индекс ✅ [*][code]Table_C.account_fk[/code] — НЕКЛАСТЕРИЗИРОВАННЫЙ индекс ✅ [*][code]Table_C.manager1_fk[/code] через менеджер7_fk - отдельные НЕКЛАСТЕРНЫЕ индексы ✅ [*][code]Table_D.user_id[/code] - КЛАСТЕРНЫЙ индекс ✅ [/list] [b]Проблема:[/b] Проблема в том, что ОДНА запись в таблице A может иметь: [list] [*]Несколько строк в Table_B (например, 10 записей) [*]Несколько строк в Table_C (например, 370 записей COUNTRY) [/list] Это создает декартово произведение: 10 × 370 = 3700 строк на каждую запись в таблице A, которое затем присоединяется к Table_D семь раз для поиска менеджера. [b]План выполнения показывает:[/b] [list] [*]Оба индексы используются эффективно (индексный поиск в столбцах соединения). [*]Однако предполагаемое количество строк варьируется от 500 тысяч до 27 миллионов и более промежуточных строк. [*]7 последующих объединений в Table_D работают с этими 27 миллионами строк. [/list] [b]Вопросы:[/b] [list] [*]Это просто проблема с бизнес-логикой/проектированием, или мне не хватает какой-то стратегии индексирования? [*]Все столбцы объединения имеют индексы. Почему SQL Server по-прежнему работает медленно, если использует поиск по индексу? [*]Помогут ли составные индексы на (account_fk, delete_flag), или декартово произведение делает индексацию неактуальной? [*]Есть ли подсказки по запросам (HASH JOIN, MERGE JOIN), которые могут помочь, или мне нужно фундаментально реструктурировать представление? [/list] [b]Что я пробовал:[/b] [list] [*]Добавлены покрывающие индексы → минимальное улучшение [*]Использованы подсказки запроса (OPTION (HASH JOIN)) → то же декартово произведение, другой алгоритм соединения [*]Проверен план выполнения → подтверждает, что индексы используются, но узким местом является развертывание строк. [/list] Является ли декартово произведение фундаментально неисправимым с помощью одних только индексов, или я что-то упускаю?