Как повысить производительность кластеризованного индекса
Я пытаюсь улучшить производительность в запросе, который работает очень медленно. Пройдя через План фактического исполнения; Я обнаружил, что Clustered Index Seek занимает 82%. Есть ли какой-либо способ улучшить производительность в поисках индекса? Ниже приведен образ проблемы Index Seek из плана выполнения, а также индекс и таблица, которые он использует.
alt text http://img340.imageshack.us/img340/1346/seek.png
Индекс
/****** Object: Index [IX_Stu] Script Date: 12/28/2009 11:11:43 ******/
CREATE CLUSTERED INDEX [IX_Stu] ON [dbo].[stu]
(
[StuKey] ASC
)WITH (PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]
Таблица (некоторые столбцы опущены для краткости):
CREATE TABLE [dbo].[stu](
[StuCertKey] [int] IDENTITY(1,1) NOT NULL,
[StuKey] [int] NULL
CONSTRAINT [PK_Stu] PRIMARY KEY NONCLUSTERED
(
[StuCertKey] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
Ответы
Ответ 1
Я обобщаю здесь, но...
Поиск кластеризованного индекса, по большей части, является наилучшим вариантом. Единственное, что я могу придумать для повышения производительности, это:
- Обновите запрос, чтобы вернуть меньшее количество строк/столбцов, если это возможно;
- Дефрагментировать или перестроить индекс;
- Разделение индекса на несколько дисков/серверов.
Если он возвращает только 138 строк, а это медленнее... возможно, это блокируется каким-то другим процессом? Вы тестируете это отдельно или другие пользователи/процессы в Интернете одновременно? Или, может быть, это даже проблема с оборудованием, например, сбой диска.
Ответ 2
Поиск кластеризованного индекса происходит, когда используются некластеризованные индексы и не обязательно являются плохими.
Рассмотрим следующий запрос:
SELECT s.StuKey, s.Name, s.Address, s.City, s.State FROM stu s WHERE State='TX'
Если в StuKey есть только кластерный индекс, то у Sql Server только 1 опция, он должен проверять всю таблицу, ищущую строки, где State = "TX", и возвращать эти строки.
Если вы добавите некластеризованный индекс в State
CREATE INDEX IX_Stu_State on Stu (State)
Теперь у Sql-сервера есть новая опция. Он может выбрать поиск некластеризованного индекса, который будет создавать строки, где State = 'TX'. Однако, чтобы вернуть оставшиеся столбцы в SELECT, он должен искать эти столбцы, выполняя кластерный поиск индекса для каждой строки.
Если вы хотите уменьшить поиск кластеризованных индексов, вы можете сделать свой индекс "закрывающим", включив в него дополнительные столбцы.
CREATE INDEX IX_Stu_State2 on Stu (State) INCLUDE (name, address, city )
Этот индекс теперь содержит все столбцы, необходимые для ответа на указанный выше запрос. Запрос будет искать индекс, чтобы возвращать только строки, где State = 'TX', а дополнительные столбцы могут быть выведены из некластеризованного индекса, поэтому поиск кластерного индекса исчезает.
Ответ 3
Поиск кластеризованного диапазона индексов, который возвращает 138 строк, не является вашей проблемой.
Технически вы можете улучшить производительность поиска, сделав кластеризованный индекс более узким:
Оба могут иметь весьма драматическое влияние на время поиска по диапазону, поскольку они уменьшают IO и необходимость ударить физические чтения. Конечно, как обычно, результат будет зависеть от большого количества других факторов, например, какие столбцы вы проецируете (вытеснение проецируемого столбца в блок выделения BLOB может иметь негативные последствия для некоторых запросов). Как побочная заметка, обычно фрагментация будет иметь лишь незначительное влияние на такое короткое сканирование. Опять же, это зависит.
Но, как я уже сказал, я очень сомневаюсь, что это ваша настоящая проблема. Вы опубликовали только отдельные части плана и результаты собственного анализа. Истинная первопричина может зависеть совсем в другом месте.
Ответ 4
Мысли...
-
Почему кластер IX_Stu? Внутри SQL Server добавляет 4-байтовый "уникальный идентификатор" к неистинным кластеризованным индексам. Какое оправдание? Это также раздувает ваш ПК тоже
-
Каков фактический запрос, который вы используете?
-
Наконец, почему FILLFACTOR 80%?
Edit:
-
"Нормальный" FILLFACTOR будет 90%, но это правило только
-
Запрос соединения 11? Это, скорее всего, ваша проблема. Каковы ваши JOIN, WHERE и т.д.? Каков полный текст плана?
Ответ 5
Вы пробовали некоторое обслуживание по этому индексу? Как дефрагментировать это? Кажется действительно странным, что это дорого стоит (120.381). Индексный поиск - это самая быстрая операция индекса, не так долго. Вы можете отправить запрос?
Ответ 6
Что произойдет, если вы жестко определите критерии WHERE, например:
SELECT StuCertKey, StuKey FROM stu
WHERE stuKey in (/* list 50 values of StuKey here */)
Если он все еще очень медленный, у вас есть внутренняя проблема. Если это быстрее, то индекс не является вашим узким местом, это JOINs, которые вы делаете, чтобы создать фильтр WHERE.
Обратите внимание, что SELECT *
может быть очень медленным, если есть много больших столбцов, и особенно если есть BLOB.
Ответ 7
Некоторые общие рекомендации: когда я должен выполнять оптимизацию запросов, я начинаю с того, что считаю, что план выполнения должен быть.
Как только я решил, что, по моему мнению, должен быть план выполнения, я пытаюсь сделать фактический запрос подходящим для этого плана. Методы для этого различны для каждой СУБД и не обязательно переходят от одного к другому или даже иногда к различным версиям СУБД.
Следует иметь в виду, что СУБД может выполнять только одно соединение за раз: оно начинается с двух начальных таблиц, присоединяет их, а затем берет результат этой операции и присоединяет ее к следующей таблице. Цель каждого шага состоит в том, чтобы свести к минимуму количество строк в промежуточном результирующем наборе (точнее, чтобы свести к минимуму количество блоков, которые нужно читать для получения промежуточных результатов, но это обычно означает наименьшее количество строк).
Ответ 8
Проверьте статистическую статистику.
reCalculating статистика кластеризованного индекса решит проблему.
в моем случае, я искал 30 записей в 40M.
в плане исполнения говорится, что он проходит через кластеризованный индекс, но он занял около 200 мс. и индекс не был дефрагментирован. после пересчета его статистики, это делается до 10 мс!
Ответ 9
Восстановить индекс и рассчитать статистику?
Единственный способ, с помощью которого я могу ускорить его, - это разбить таблицу, которая может быть или не быть возможной.