#sql-server #performance #query-optimization #columnstore
Вопрос:
В SQL Server у меня есть таблица, использующая индекс Columnstore, нужно выполнить какой-то агрегированный шаг, но если предложение where содержит «или», выпадающий список предикатов исчезнет, я не знаю, почему, у кого-нибудь есть предложения по этому поводу? Например,
В этом тексте запроса:
select sum(num) from Fact where date = '2021-06-02' and NUMF = 23
Отжимание предиката будет работать идеально. Но если я добавлю «ИЛИ» в предложение where, например:
select sum(num) from Fact where date = '2021-06-02' or NUMF = 23
выпадающий список предикатов не будет работать, план запроса будет сканировать весь индекс columnstore, что занимает очень много времени.
Является ли это особенностью SQLServer? Или жучок?
Комментарии:
1. Как для этого подходит perf?
select sum(num) as num from ( select sum(num) as num from Fact where date = '2021-06-02' union all select sum(num) as num from Fact where NUMF = 23 and date <> '2021-06-02' ) t
(предполагаетсяdate
, что оно не может быть аннулировано)2. @MartinSmith Спасибо за ваш ответ, уверен, что качество этого текста запроса отличное, предикат работает, но иногда текст запроса будет очень сложным и его будет сложно изменить, чтобы использовать «ОБЪЕДИНЕНИЕ ВСЕХ», например: выберите сумму(число) из факта, где дата = ‘2021-06-02’ или NUMF = 23, или столбец 1 = 1, или столбец 2 = 2, или столбец 3, или столбец 4 = 4. Поэтому я думаю, что неплохо использовать «объединение всех», но масштабируемость недостаточно хороша.
Ответ №1:
ИЛИ предикаты в одном столбце выталкиваются вниз, но когда вы используете предикат ИЛИ в разных столбцах, он не может быть вытеснен. UNION ALL
Обходной путь также выделен в этом сообщении. Если вы подумаете о том, как вы это реализовали, это имеет смысл: columnstore обрабатывает данные по столбцу за раз.
Одна из причин, по которой столбчатая обработка выполняется быстро, заключается в том, что вы работаете с одним столбцом за раз и отслеживаете строки в столбце, которые определяют ваш предикат для этого столбца. Как только вы закончите со всеми оценками предикатов, вы можете вернуться к строкам из агрегированного столбца и вычислить агрегат.
Таким образом, легко оценить ИЛИ предикаты в одном столбце, и вы можете обновить список строк, если у вас есть И предикаты. В случае, если строка не соответствует более позднему предикату, вы всегда можете удалить ее из списка. Однако, если у вас есть предикаты ИЛИ в нескольких столбцах и несколько предикатов, порядок оценки действительно имеет значение, и вам, возможно, потребуется несколько раз возвращаться к одному и тому же столбцу, поэтому я думаю, что стоимость реализации была слишком высока, чтобы это произошло в механизме хранения. Я думаю, что удаление всех ИЛИ предикатов должно быть выполнимым, хотя это, вероятно, добавляет дополнительную сложность для исключения сегментов.