2009-11-11 2 views
18

В моей таблице (SQL Server 2008) есть 1 миллион + записей, когда я пытаюсь заказать записи по дате, это занимает 1 секунду, но когда я заказываю по ID (int), это занимает всего около 0,1 секунды.SQL Server 2008: упорядочение по дате времени слишком медленное

Есть ли способ повысить эффективность? (Я уже добавил столбец datetime в индекс)

+0

В каких "РСУБД" вы используете? – Quassnoi

+0

Я использую SQL Server 2008 – silent

+7

- это то, что столбец datetime в отдельном индексе? Вы говорите «добавили .. к индексу» ....если столбец datetime является, например, столбец №. 3 в составном индексе, который вообще не поможет при попытке заказать этот столбец datetime ........ –

ответ

23

Заказ на id, вероятно, использует сканирование с кластерным индексом, а порядок datetime использует сортировку или поиск по индексу.

Оба эти метода являются более медленными, чем кластерное сканирование индекса.

Если ваш стол сгруппирован по id, в основном это означает, что он уже отсортирован. Записи содержатся в файле B+Tree, который имеет связанный список, связывающий страницы в заказе id. Двигатель должен просто пересечь связанный список, чтобы получить записи, упорядоченные по id.

Если id s были вставлены в последовательном порядке, это означает, что физический порядок строк будет соответствовать логическому порядку, а сканирование кластерного индекса будет еще быстрее.

Если вы хотите, чтобы ваши записи будут отсортированы по datetime, есть два варианта:

  • Возьмите все записи из таблицы и сортировать их. Медленность очевидна.
  • Используйте индекс на datetime. Индекс хранится в отдельном пространстве диска, это означает, что движок должен перемещаться между индексными страницами и страницами таблицы во вложенном цикле. Это медленнее.

Для улучшения заказа, вы можете создать отдельный индекс покрытия datetime:

CREATE INDEX ix_mytable_datetime ON mytable (datetime) INCLUDE (field1, field2, …) 

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

Этот индекс похож на теневую копию таблицы, но с данными, отсортированными в другом порядке.

Это позволит избавиться от ключевых поисков (поскольку индекс содержит все данные), который будет делать упорядочение на datetime так же быстро, как на id.

Update:

Свежее сообщение в блоге на эту проблему:

+0

Есть ли эффективный способ для этого? – silent

+0

Я считаю, что база данных сохранит ее в этом формате (и likey сравнивает ее так же). Сначала я тоже думал об одном и том же, но я не верю, что это должен быть ответ. – Jrud

+1

+1 Чтобы оптимизировать сортировку datetime, сделайте datetime кластеризованным индексом, а индекс id - некластеризованным первичным ключом. – Andomar

0

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

вы должны проверить на своем сервере, как он хранит дату и время, ваш сервер уже сохраняет его как int или bigint. ничего не меняет ....

2

Добавить дату в новый индекс, добавив его в идентификатор, все равно не поможет.

0

Если ваше поле datetime содержит много разных значений, и эти значения редко меняются, определите кластерный индекс в поле datetime, это отсортирует фактические данные по значению даты и времени. См. http://msdn.microsoft.com/en-us/library/aa933131(SQL.80).aspx для использования кластеризованных индексов.

Это приведет к тому, что поиск в Интернете будет медленнее, поскольку они будут отнесены к использованию некластеризованного индекса.

1

Может быть, есть индекс для столбца int, но не для столбца datetime? Посмотрите план выполнения.

+0

+1 хорошая точка - проверьте план выполнения! Используется ли индекс вообще? –

0

Вы добавили поле DateTime в индекс «или» или в индекс? Вы фильтруете свой выбор другим полем и DateTime или только этим?

У вас должен быть индекс со всеми полями, которые вы фильтруете, и предпочтительно в том же порядке, чтобы оптимизировать производительность.

+0

Я добавил его к существующему индексу, я просто попытался создать новый индекс, он становится относительно быстрым (0,5 секунды), но все же медленнее, чем столбец int. – silent

+0

Важно сделать хороший индекс, смотрящий на поля в операторах «WHERE» и «ORDER BY» (и «GROUP BY», если таковые имеются). Это должны быть те же поля и в том же порядке. Если вам не нужен каждый столбец в таблице, сделайте SELECT только с нужными полями. Затем очистите кеш и статистику и попробуйте результаты. Также подумайте, что для выбора с одинаковой скоростью кластеризованного индекса в таблицах с большим количеством данных. Вот почему тщательно выбирать, какой должен быть кластеризованный. –

6

В честь ORDER BY двигатель имеет два варианта:

  • сканирования строки с помощью индекса, который предлагает заказ просил
  • сортирует строки

Первый вариант быстр, второй медленный. Проблема в том, что для использования индекс должен быть , охватывающим. Это означает, что он содержит все столбцы в списке проекции SELECT и все столбцы, используемые в предложениях WHERE (как минимум). Если индекс не покрывает, то для поиска значений требуемых столбцов движок должен искать кластерный индекс (т. Е. Таблицу) для каждой строки. Этот постоянный поиск значений является дорогостоящим, и есть решающий момент, когда двигатель (по праву) решит более эффективно просто сканировать кластерный индекс и сортировать результат, фактически игнорируя ваш некластеризованный индекс. Для получения дополнительной информации см. The Tipping Point Query Answers.

Рассмотрим следующие три запроса:

SELECT dateColumn FROM table ORDER BY dateColumn 
SELECT * FROM table ORDER BY dateColumn 
SELECT someColumn FROM table ORDER BY dateColumn 

Первый из них будет использовать некластеризованной индекс dateColumn. Но второй не будет использовать индекс на dateColumn, скорее всего, выберем сканирование и сортировку вместо 1M строк. С другой стороны, третий запрос может извлечь выгоду из индекса на Table(dateColumn) INCLUDE (someColumn).

Этот раздел подробно рассматривается в MSDN. Index Design Basics, General Index Design Guidelines, Nonclustered Index Design Guidelines или How To: Optimize SQL Indexes.

В конечном счете, самым важным выбором дизайна вашего стола является кластеризованный индекс, который вы используете. Почти всегда первичный ключ (как правило, автоматически увеличиваемый идентификатор) остается как кластеризованный индекс, решение, которое приносит пользу только определенным нагрузкам OLTP.

И, наконец, довольно очевидный вопрос: почему в мире вы бы заказали 1 миллион строк? Вы не можете их отобразить, не так ли? Объяснение немного больше о вашем случае использования может помочь нам найти лучший ответ для вас.

+0

Спасибо, Ремус, я не хочу отображать 1 миллион + записей за один раз, я использую метод row_number() для подкачки, но обнаружил, что при попытке просмотреть большое число, например страницу 50000 (20 rec/page), запрос становится очень медленным, но если я изменю метод упорядочения на ID, он будет почти в 10 раз быстрее. – silent

+1

Я думал, что это должна быть строка с номером строки. Это LINQ, случайно? Лучше всего выразить запрос следующим образом: выберите идентификаторы интересующей вас страницы (под редакцией 20 идентификаторов на стр. 17), затем получите сведения о этих 20 записях. Этот * может * быть выражен в T-SQL, а также в LINQ и может быть достаточно быстрым. Вам лучше разместить схему и запросы. –

Смежные вопросы