Запрос с заказом на один стол - PullRequest
0 голосов
/ 06 мая 2020

У меня есть таблица T с PK Id, двумя полями FieldA, FieldB и полем даты.

Я выполняю запрос (на SQLServer):

select top(N) *
from T 
where (FieldA=Value1 OR FieldB=Value2) AND Date < GivenDate 
ORDER BY Date DESC

Если у меня есть следующие два индекса в таблице:

  • (FieldA ASC)
  • (FieldB ASC)

Запрос "не очень хорошо работает", если есть много вхождений Value1 или Value2, потому что нет информации о Date, и движок должен прочитать все совпадающие строки и отсортировать.

Я решил изменить индексы на:

  • (FieldA ASC, Date DESC)
  • (FieldB ASC, Date DESC)

Но это ничего не меняет: «Фактическое количество прочитанных строк» ​​- это общее количество строк, соответствующих значениям.

Я предполагал, что движок будет достаточно умен, чтобы получить не более N строк из каждого индекса и отсортировать (я думаю)?

Может ли он это сделать, НО его оценка на основе затрат достаточно низкая, чтобы решить использовать это план выполнения?

Наверняка движку не так-то просто угадать. Но есть ли другой способ улучшить такой запрос?

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Вы уверены, что используются один или несколько индексов?

Если вы убедитесь, что они не используются (как я думаю), принудительно установите хотя бы один из них с помощью From T with (INDEX (Index_name-here)) ... Если вы хотите принудительно использовать оба индекса, вам придется выполнить внутреннее соединение с той же таблицей и установить там второй индекс.

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

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

С уважением

0 голосов
/ 06 мая 2020

Я бы рекомендовал использовать SQL Management Studio для проверки наилучшего использования индекса. Это очень помогает. Во-первых, я бы поставил дату в первую позицию, так как она наиболее часто используется (даже если она ничего не меняет в этом случае).

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

В-третьих, если вы не можете сделать заказ в коде Java или C# иногда лучше создать свой выбор без порядка, поместить результат во временную таблицу с индексом по дате, а затем выбрать из этой временной таблицы с порядком. Вы должны посмотреть на план выполнения, чтобы увидеть, какой из них лучше.

Затем вы также можете попробовать использовать включенные индексы вместо индексов с несколькими столбцами. Что-то вроде:

CREATE NONCLUSTERED INDEX IX_MYINDEX
ON T(Date)
INCLUDED (FieldA, FieldB)

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

...