Какие столбцы индексировать - PullRequest
1 голос
/ 24 июня 2019

Чтобы следующий запрос выполнялся быстро, какие столбцы я должен добавить в индекс?

select max(id) from tb 
group by BranchId,ArticleID
having count(*)>1

Ответы [ 2 ]

4 голосов
/ 24 июня 2019

Ваш текущий запрос может не принести пользу ни одному индексу из-за термина count(*) > 1, который SQL Server может интерпретировать как получение полного подсчета каждой группы. Но мы можем переписать ваш запрос следующим образом, чтобы он мог использовать индекс:

SELECT MAX(id)
FROM tb
GROUP BY BranchId, ArticleID
HAVING MIN(id) <> MAX(id);

Затем добавьте следующий индекс:

CREATE INDEX idx ON tb (BranchId, ArticleID, Id);

Хитрость здесь в том, чтобы перефразировать count(*) > 1 как логически эквивалентное наименьшему и наибольшему id значению в группе , а не , которое является одинаковым. Обратите внимание, что здесь я предполагаю, что id является уникальным столбцом, то есть в данной группе никогда не будет двух или более записей с одинаковым значением id.

1 голос
/ 25 июня 2019

Помимо того, что Тим уже рассмотрел в индексах ROWSTORE, я хочу сделать еще несколько комментариев здесь вместе с демонстрацией:

До тех пор, пока вы можете написать запрос таким образом, чтобы вы могли сделать столбцы ' search ' (столбцы, используемые в выражении where, объединения, группировки по, order by, отличные) Seargable (когда запрос может использовать индексированные столбцы), индексы ROWSTORE в порядке. Но есть много ситуаций, когда вам может быть трудно поддерживать то же самое или у вас может быть лучший подход, некоторые из них:

  1. Необходимость усложнить запрос, чтобы убедиться, что вы можете использовать индексы ROWSTORE
  2. Когда вам нужно использовать определенный CAST в предложении where или присоединении
  3. Когда вам нужно использовать функции в предложении where --- Но попробуйте чтобы избежать этого в любом случае в вашем коде как лучшая практика
  4. Когда вам нужно использовать LIKE в ваших запросах (Col1 LIKE '% foo%')
  5. Когда вам нужно выполнить агрегаты и группировать по
  6. Пользователи постоянно выполняют сортировку по разным столбцам.
  7. И еще один самый важный момент: если у вас мало кардинальных значений в ваших «искомых» столбцах, ваши индексы ROWSTORE не очень помогают. Но здесь индекс COLUMNSTORE действительно может сиять.
  8. Ваше главное ожидание - PAGEIOLATCH (чтение страниц данных с диска)
  9. Ваши таблицы очень широки, но пользователи отчетов не используют все столбцы.

Затем использование индекса 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

Логические чтения и истекшее время :

enter image description here

Планы выполнения:

enter image description here

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)

Логическое чтение и истекшее время :

enter image description here

Планы выполнения: enter image description here

...