Разумный выбор первичного ключа и кластерного индекса для таблицы в SQL 2005 для повышения производительности при выборе одной записи или нескольких записей - PullRequest
1 голос
/ 06 февраля 2009

РЕДАКТИРОВАТЬ: Я добавил столбец «Slug» для решения проблем производительности при выборе конкретной записи.

В моей таблице есть следующие столбцы.

Id Int - Primary key (identity, clustered by default)
Slug varchar(100)
...
EntryDate DateTime

В большинстве случаев я упорядочиваю оператор select по EntryDate, как показано ниже.

Select T.Id, T.Slug, ..., T.EntryDate
From (
    Select Id, Slug, ..., EntryDate,  
        Row_Number() Over (Order By EntryDate Desc, Id Desc) AS RowNum
    From TableName
    Where ...
) As T
Where T.RowNum Between ... And ...

Я заказываю его по EntryDate и Id на случай дублирования EntryDate.

Когда я выбираю запись A, я делаю следующее.

Select Id, Slug, ..., EntryDate
From TableName
Where Slug = @slug And Year(EntryDate) = @entryYear 
    And Month(EntryDate) = @entryMonth

У меня есть уникальный ключ Slug & EntryDate.

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

Должен ли я установить Id в качестве некластеризованного первичного ключа и EntryDate в качестве кластеризованного индекса?

Я ценю всю вашу помощь. Спасибо.

EDIT:

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

Ответы [ 5 ]

1 голос
/ 07 февраля 2009

Исходя из текущего макета таблицы, вам нужны такие индексы, как этот.

CREATE INDEX IX_YourTable_1 ON dbo.YourTable
(EntryDate, Id)
INCLUDE (SLug)
WITH (FILLFACTOR=90)

CREATE INDEX IX_YourTable_2 ON dbo.YourTable
(EntryDate, Slug)
INCLUDE (Id)
WITH (FILLFACTOR=80)

Добавьте все остальные столбцы, которые вы возвращаете, в строку INCLUDE.

Измените ваш второй запрос на что-то вроде этого.

Select Id, Slug, ..., EntryDate
From TableName
Where Slug = @slug 
    AND EntryDate BETWEEN CAST(CAST(@EntryYear AS VARCHAR(4) + CAST(@EntryMonth AS VARCHAR(2)) + '01' AS DATE) AND DATEADD(mm, 1, CAST(CAST(@EntryYear AS VARCHAR(4) + CAST(@EntryMonth AS VARCHAR(2)) + '01' AS DATE))

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

0 голосов
/ 07 февраля 2009

Кластерный индекс будет иметь какое-либо значение, только если вы возвращаете набор записей, а некоторые возвращаемые вами поля не являются частью индекса. В противном случае нет никакой пользы.

Сначала вам нужно выяснить, что план запроса говорит вам о том, почему ваши текущие запросы медленные. Без этого это в основном пустые спекуляции (которые обычно контрпродуктивны при оптимизации запросов.)

Я бы не стал ничего пробовать (предложенный мной или кем-либо еще), если бы у меня не было надежного плана запросов, с которым можно было бы сравнить, чтобы хотя бы узнать, хорошо ли вы делаете или вредите.

0 голосов
/ 06 февраля 2009

Вы хотите сохранить идентификатор в качестве кластеризованного индекса, так как вы, скорее всего, присоединитесь к таблице, используя свой идентификатор, а не дату входа.

Простой некластеризованный индекс, содержащий только поле даты, может помочь ускорить процесс.

0 голосов
/ 06 февраля 2009

Кластеризация немного похожа на «индексную подкачку», индекс «разбит на части», а не просто длинный список. Это полезно, когда у вас много данных. БД может искать в диапазонах кластеров, а затем находить отдельные записи. Это делает индекс меньшим, следовательно, более быстрым для поиска, но менее специфичным. Однажды, если найдет правильное место в кластере, он должен искать в кластере.

Это быстрее с большим количеством данных, но медленнее с меньшими наборами данных.

Если вы не ищете много, используя первичный ключ, тогда кластеризуйте дату и оставьте первичный ключ некластеризованным. Это действительно зависит от того, насколько сложны ваши запросы с объединением других таблиц.

0 голосов
/ 06 февраля 2009

Вы пытались просто добавить некластеризованный индекс на дату входа, чтобы увидеть, какой прирост производительности вы получаете?

Кроме того, как часто добавляются новые данные? и будут ли новые данные, которые будут добавлены, всегда быть> = последней EntryDate?

...