Столкнулся с проблемой, в поисках решения которой уже сломал голову и замучил гугл.
Допустим, у нас есть 2 таблицы:
1) clients (subid int PK, card_num int, class_num int FK)
2) classes (class_num int PK, classid int UQ)
В первой таблице у нас десятки миллионов строк. Во второй - просто пара десятков. Для таблицы clients есть покрывающий индекс по столбцу class_num (include card_num, subid), есть свежая актуальная статистика (распределение количества записей по card_num ни разу не равномерное - для каких-то значение миллионы, для других единицы).
Мы пытаемся получить данные довольно простым запросом:
В плане выполнения видим непонятную мне мистику. Планировщик, при определении кардинальности извлекаемых их clients строк, берет среднее значение, которое меньше реально извлекаемого на порядок (примерно 1кк против 10кк). Отсюда следует неправильная оценка общей стоимости плана выполнения и spill промежутощных данных в temp_db, которого очень бы хотелось избежать.
Я пробовал перестраивать индексы, добавлять фильтрующую статистику - не помогает. Использование хинтов для джоинов тоже не дает положительных результатов. Option (recompile) - не спасает.
Причина по большей части кроется в условии
Пока склоняюсь к тому, что в SQL Serverv 2012 SP1 есть баг с определением кардинальности в определнных условиях, но не хочу в это верить. :)
Кто-нибудь сталкивался с такой проблемой? Как это победить?
Допустим, у нас есть 2 таблицы:
1) clients (subid int PK, card_num int, class_num int FK)
2) classes (class_num int PK, classid int UQ)
В первой таблице у нас десятки миллионов строк. Во второй - просто пара десятков. Для таблицы clients есть покрывающий индекс по столбцу class_num (include card_num, subid), есть свежая актуальная статистика (распределение количества записей по card_num ни разу не равномерное - для каких-то значение миллионы, для других единицы).
Мы пытаемся получить данные довольно простым запросом:
select cli.subid, cli.card_num, cla.classid from clients cli inner join classes cla on cla.class_num = cli.class_num where cli.classid = 1
В плане выполнения видим непонятную мне мистику. Планировщик, при определении кардинальности извлекаемых их clients строк, берет среднее значение, которое меньше реально извлекаемого на порядок (примерно 1кк против 10кк). Отсюда следует неправильная оценка общей стоимости плана выполнения и spill промежутощных данных в temp_db, которого очень бы хотелось избежать.
Я пробовал перестраивать индексы, добавлять фильтрующую статистику - не помогает. Использование хинтов для джоинов тоже не дает положительных результатов. Option (recompile) - не спасает.
Причина по большей части кроется в условии
where cli.classid = 1- в плане выполнения планировщик вместо конкретного значение подставляет Scalar Operator([classes].[class_num] as [cla].[class_num]).
Пока склоняюсь к тому, что в SQL Serverv 2012 SP1 есть баг с определением кардинальности в определнных условиях, но не хочу в это верить. :)
Кто-нибудь сталкивался с такой проблемой? Как это победить?