Проблема производительности индекса хранилища столбцов SQLServer: «Где ИЛИ» повлияет на выталкивание предиката

#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 обрабатывает данные по столбцу за раз.

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

Таким образом, легко оценить ИЛИ предикаты в одном столбце, и вы можете обновить список строк, если у вас есть И предикаты. В случае, если строка не соответствует более позднему предикату, вы всегда можете удалить ее из списка. Однако, если у вас есть предикаты ИЛИ в нескольких столбцах и несколько предикатов, порядок оценки действительно имеет значение, и вам, возможно, потребуется несколько раз возвращаться к одному и тому же столбцу, поэтому я думаю, что стоимость реализации была слишком высока, чтобы это произошло в механизме хранения. Я думаю, что удаление всех ИЛИ предикатов должно быть выполнимым, хотя это, вероятно, добавляет дополнительную сложность для исключения сегментов.