Правильная индексация таблицы дает перечисленные запросы

#sql-server #sql-server-2008 #indexing

#sql-сервер #sql-сервер-2008 #индексирование

Вопрос:

У меня есть следующая таблица в SQL Server:

 CREATE TABLE [dbo].[Users](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Email] [varchar](128) NOT NULL,
    [CreatedAt] [datetime] NOT NULL,
    [SourceId] [int] NOT NULL
PRIMARY KEY CLUSTERED 
(
    [Id] ASC
) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,  ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
 

У этой таблицы есть потенциал для роста. Наиболее частыми запросами, выполняемыми в этой таблице, будут:

 SELECT * FROM Users WHERE Email = 'some@email.com'
SELECT * FROM Users WHERE Email = 'some@email.com' AND SourceId = some integer
SELECT * FROM Users WHERE CreatedAt BETWEEN '2011-10-01' AND '2011-10-30'
SELECT * FROM Users WHERE CreatedAt BETWEEN '2011-10-01' AND '2011-10-30' AND SourceId = some integer
 

В настоящее время я настроил следующие индексы:

 CREATE INDEX IX_Users_Email_SourceId ON Users (Email, SourceId)
CREATE INDEX IX_Users_CreatedAt ON Users (CreatedAt)
CREATE INDEX IX_Users_SourceId ON Users (SourceId)
 

Достаточны ли эти индексы для типов запросов, перечисленных выше? Должен ли я установить ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON в значение OFF, если это будет таблица с большим количеством запросов? Я немного запутался в том, как правильно настроить индексы.

Ответ №1:

Я бы проиндексировал их таким образом:

 WHERE Email = 'some@email.com'
index: Email
or Email, SourceId

WHERE Email = 'some@email.com' AND SourceId = some integer
index: SourceId, Email
or Email, SourceId

WHERE CreatedAt BETWEEN '2011-10-01' AND '2011-10-30'
index: CreatedAt
or CreatedAt, SourceId 

WHERE CreatedAt BETWEEN '2011-10-01' AND '2011-10-30' AND SourceId = some integer
index: SourceId, CreatedAt 
or CreatedAt, SourceId
 

Трудно быть полностью уверенным в том, в чем заключается избирательность SourceId . В зависимости от этого вы можете попытаться охватить несколько запросов одним индексом (первые два могут быть объединены, а последние два могут быть объединены). If SourceId очень выборочно (несколько строк соответствуют каждому значению) Я бы не хотел объединять индексы и добиваться максимальной производительности, используя четыре индекса.

Кроме того, вы не указываете, сколько ВСТАВОК / ОБНОВЛЕНИЙ вы ожидаете, поэтому трудно определить, насколько будут увеличиваться накладные расходы на большее / меньшее количество индексов.

Кроме того, вы SELECT * не можете рекомендовать покрывающие индексы и т. Д.

Комментарии:

1. Спасибо, КМ. Должен ли я отключить блокировку строк и страниц или это плохая идея? SourceID не будет очень избирательным. Будет много ВСТАВОК (но не так много ОБНОВЛЕНИЙ).

2. вы беспокоитесь о блокировках, основанных на частоте ВСТАВКИ / ОБНОВЛЕНИЯ / УДАЛЕНИЯ, а также на продолжительности их транзакций. Если вы в основном часто используете только SELECTING эти данные и не меняете их при длительных медленных транзакциях, я бы не стал беспокоиться об этом, пока у вас не начнутся проблемы.