Помимо того, что Тим уже рассмотрел в индексах ROWSTORE, я хочу сделать еще несколько комментариев здесь вместе с демонстрацией:
До тех пор, пока вы можете написать запрос таким образом, чтобы вы могли сделать столбцы ' search ' (столбцы, используемые в выражении where, объединения, группировки по, order by, отличные) Seargable (когда запрос может использовать индексированные столбцы), индексы ROWSTORE в порядке. Но есть много ситуаций, когда вам может быть трудно поддерживать то же самое или у вас может быть лучший подход, некоторые из них:
- Необходимость усложнить запрос, чтобы убедиться, что вы можете
использовать индексы ROWSTORE
- Когда вам нужно использовать определенный CAST в предложении where или присоединении
- Когда вам нужно использовать функции в предложении where --- Но попробуйте
чтобы избежать этого в любом случае в вашем коде как лучшая практика
- Когда вам нужно использовать LIKE в ваших запросах (Col1 LIKE '% foo%')
- Когда вам нужно выполнить агрегаты и группировать по
- Пользователи постоянно выполняют сортировку по разным столбцам.
- И еще один самый важный момент: если у вас мало кардинальных значений в ваших «искомых» столбцах, ваши индексы ROWSTORE не очень помогают. Но здесь индекс COLUMNSTORE действительно может сиять.
- Ваше главное ожидание - PAGEIOLATCH (чтение страниц данных с диска)
- Ваши таблицы очень широки, но пользователи отчетов не используют все столбцы.
Затем использование индекса COLUMNSTORE может обеспечить впечатляющее повышение производительности благодаря его массивному сжатию данных для значений столбцов, поступающих из аналогичного домена. В SQL Server 2017 пакетное выполнение может еще больше повысить производительность. Индекс Columnstore также дает лучший индекс реорганизации результатов.
Я привел некоторые из вышеперечисленных пунктов из презентации Брента Озара.
Вот демонстрация, где я подготовил 2 точно такие же таблицы по 10 миллионов строк в каждой с определенным уровнем мощности.
Подготовка данных :
--Test table1
drop table if exists dbo.dummy
select top 10000000 objectid1 = a.object_id, Name1 = a.name, objectid2 = b.object_id, Name2 = b.name, objectid3 = c.object_id, Name3 = c.name
into dbo.dummy
from sys.objects a
cross join sys.objects b
cross join sys.objects c
order by a.object_id, a.name
drop index if exists ix_dummy on dbo.dummy
go
--create a nonclustered rowstore index
create index ix_dummy on dbo.dummy (objectid1, objectid2, objectid3)
go
--Test Table2
drop table if exists dbo.dummy2
select top 10000000 objectid1 = a.object_id, Name1 = a.name, objectid2 = b.object_id, Name2 = b.name, objectid3 = c.object_id, Name3 = c.name
into dbo.dummy2
from sys.objects a
cross join sys.objects b
cross join sys.objects c
order by a.object_id, a.name
drop index if exists ix_dummy2 on dbo.dummy2
go
--create a nonclustered columnstore index
create nonclustered columnstore index ix_dummy2 on dbo.dummy2 (objectid1, objectid2, objectid3)
go
set statistics io on
set statistics time on
1: при простом поиске:
Процент и Чтения говорят, что Индекс Columnstore является Победителем, но Истекшее время говорит, что Индекс Rowstore является Победителем
--Simple search
--Run these 2 queries together and compare their percantage of time taken with respect each other, logical read, elapsed time.
select objectid3
from dbo.dummy
where objectid1 in (5) -- look for some object_id that exists in your database
select objectid3
from dbo.dummy2
where objectid1 in (5) -- look for some object_id that exists in your database
Логические чтения и истекшее время :
Планы выполнения:
2: агрегация и группировка по запросам: индекс Columnstore выиграл большое время
--Agregate queries
----Run these 2 queries together and compare their percantage of time taken with respect each other, logical read, elapsed time.
select max(objectid3)
from dbo.dummy
group by objectid1, objectid2
having max(objectid3) <> min(objectid3)
select max(objectid3)
from dbo.dummy2
group by objectid1, objectid2
having max(objectid3) <> min(objectid3)
Логическое чтение и истекшее время :
Планы выполнения: