странный план выполнения запроса SQL Server - PullRequest
2 голосов
/ 23 августа 2011

Контекст: SQL Server 2008. Есть 2 таблицы для внутреннего объединения.Таблица фактов, содержащая 40 миллионов строк, содержит ключ пациента, вводимые лекарства и другие факты.Существует уникальный индекс (некластеризованный) для ключа лекарства и ключа пациента, объединенный в этом порядке.Таблица измерений - это список лекарств (70 строк).Присоединение состоит в том, чтобы получить код лекарства (бизнес-код), основанный на ключе лекарства (суррогатный ключ).Запрос:

SELECT a.PKey, a.SomeFact, b.MCode
FROM tblFact a
JOIN tblDIM b ON a.MKey = b.MKey

Все возвращаемые столбцы являются целыми числами.Вышеуказанный запрос выполняется за 7 минут, и в плане его выполнения показано, что используется индекс (MKey, PKey).Индекс был перестроен прямо перед запуском.Когда я отключил индекс таблицы фактов (или скопировал данные в новую таблицу с такой же структурой, но без индекса), тот же запрос занимает всего 1:40 минут.

Статистика ввода-вывода также ошеломляет.

С индексом: Таблица 'tblFACT'.Сканирование 70, логическое чтение 190296338, физическое чтение 685138, чтение с опережением 98713

Без индекса: таблица 'tblFACT_copy'.Сканирование 17, логическое чтение 468891, физическое чтение 0, чтение с опережением 419768

Вопрос: почему он пытается использовать индекс и идти по неэффективному пути?

Ответы [ 3 ]

1 голос
/ 23 августа 2011

Вам необходимо добавить SomeFact как ВКЛЮЧЕНО в индекс tblFact, чтобы сделать его , охватывающим .

В настоящее время доступ к таблице будет выполнен дважды: один раз для индекса, а затем снова для поиска, чтобы получить SomeFact в качестве поиска RID или ключа (зависит от того, существует ли кластеризованный индекс)

Это не относится к tblDIM, потому что я предполагаю, что MKey является кластеризованным индексом, который делает его неявным образом охватывающим

0 голосов
/ 23 августа 2011

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

Могут быть директивы, побуждающие базу данных не использовать индексы или использовать другие индексы, но я не очень хорошо знаю SQL-сервер.

0 голосов
/ 23 августа 2011

Ваша статистика актуальна? Проверить с помощью:

SELECT object_name = Object_Name(ind.object_id)
,      IndexName = ind.name
,      StatisticsDate = STATS_DATE(ind.object_id, ind.index_id)
FROM   SYS.INDEXES ind
order by
       STATS_DATE(ind.object_id, ind.index_id) desc

Обновление с помощью:

exec sp_updatestats;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...