Индексный Порядок SQL Server (поле даты и времени)

У меня была похожая проблема пару недель назад, когда я пытался обновить старую версию homebrew. Делая это:

git reset --hard origin/master

в /usr/local исправили это для меня.

Похоже, у других тоже была эта проблема. Вы просматривали какие-либо из предложенных обходных путей здесь ?

7
задан Jason Kealey 9 July 2009 в 17:59
поделиться

5 ответов

Я предполагаю, что двоичный поиск в как отсортированный список QueryTime следует взглянув на первый результат в дочерний список ResultID - самый быстрый способ получения результата. (Отсюда мой начальный порядок сортировки).

Это действительно было бы быстро, но ваш запрос выражает другой запрос: вы запрашиваете Результат с минимальным ResultId из всех запросов, которые произошли после '2009-05-01' . Чтобы удовлетворить запрос, который он должен искать в начале диапазона ('2009-05-01'), запустите сканирование с этой позиции, чтобы извлечь все ResultId, отсортируйте их, а затем верните первую 1 (минимальный ResultId). Второй добавленный вами индекс [idx_ResultDate2] тоже не очень помогает. Запрос должен выполнять практически тот же поиск и сканирование: ResultId отсортированы с датой результата , чтобы узнать верхний ResultId из всех результатов после '2009 -05-01 'запрос все еще должен сканировать индекс до конца.

В вашем последнем индексе, [IDX_ResultDate3], запрос обманывает. Что он делает, он запускает сканирование по индексу и просматривает значение QueryTime, зная, что в этом индексе сканирует первый Результат, у которого QueryTime находится в желаемом диапазоне (> '2009-05-01' ) - это тот, который вам нужен (потому что ResultId гарантированно будет первым 1). Вы получаете результат за «доли секунды» благодаря чистой случайности: у вас есть соответствующий Результат в начале индекса. Запрос вполне может сканировать весь индекс и соответствовать самому последнему Результату. Вы можете вставить новый результат с QueryTime, например '2010-01-01', а затем искать его, вы увидите, что производительность ухудшается, поскольку запрос должен сканировать весь индекс до конца (все еще быстрее, чем сканирование таблицы, потому что более узкого размера индекса).

Мой вопрос: Вы абсолютно уверены, что ваш запрос должен возвращать ТОП 1 в ORDER BY ResultID? Или вы просто произвольно выбрали заказ? Если вы можете изменить запрос ORDER BY, скажем, на QueryTime, то любой из индексов ( обновлен : с QueryTime в качестве крайнего левого столбца) вернет простой поиск и выборку, без сканирования и сортировки.

12
ответ дан 6 December 2019 в 10:52
поделиться

Вы можете изменить кластерный индекс на ([QueryTime], [ResultID]) или изменить свой запрос с

select top 1 * from results where querytime>'2009-05-01' order by ResultID asc

на

select top 1 <only the columns you actually need> from results where querytime>'2009-05-01' order by ResultID asc

и включить все эти столбцы в [IDX_ResultDate2]

2
ответ дан 6 December 2019 в 10:52
поделиться

У вас есть ранжированное условие фильтрации для одного поля вместе с ORDER BY в другом поле.

Индекс, даже составной индекс, не может в этом случае будет использоваться для выполнения обоих условий.

Когда вы создаете индекс для (queryTime, resultId) , этот индекс используется для фильтрации. Механизму все еще необходимо упорядочить набор результатов.

Когда вы создаете индекс для (resultId, queryTime) , этот индекс используется для упорядочивания.

Поскольку вам нужен TOP 1 , а строка, которая удовлетворяет этому результату, оказывается в начале индекса, последний подход оказывается более эффективным.

Если ваше условие фильтрации будет выборочным (т. Е. Оно вернет несколько рядов), и первый результат, который вам нужен, будет в конце индекса, первый подход будет лучше.

См. эту статью в моем блоге, чтобы получить дополнительные объяснения и подсказки о том, какой индекс создавать в каких условиях:

4
ответ дан 6 December 2019 в 10:52
поделиться

Первое, что я бы посоветовал, - это проверить, есть ли статистика для этой таблицы (все индексы ) актуальны.

Поскольку у вас есть два разных плана выполнения с разными наборами данных, похоже, что SQL Server делает печально известный «вызов суждения», отдавая предпочтение одному плану выполнения другому.

Я согласен с объяснением Ремуса, почему вы получаете " волшебные »результаты с вашим последним index.

Его предложение тоже хорошее - вы действительно хотите упорядочить по ID результата? Или, если вы можете упорядочить по queryTime, тогда у вас будет НАМНОГО лучшая производительность, потому что план выполнения сможет использовать порядок индекса в качестве порядка набора результатов (И он будет искать через индекс, а не сканировать).

0
ответ дан 6 December 2019 в 10:52
поделиться

Я не уверен, что смогу ответить на вопрос, но хотел бы указать что ключ кластеризованного индекса уже включен как часть любого другого индекса, поэтому его избыточно включать ResultID как часть любого из других предлагаемых вами индексов.

0
ответ дан 6 December 2019 в 10:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: