Неожиданные оценочные строки в плане выполнения запросов (Sql Server 2000) - PullRequest
1 голос
/ 01 декабря 2010

если я выполню этот запрос

select user from largetable where largetable.user = 1155 

(обратите внимание, что я опрашиваю пользователя, чтобы свести это к простейшему случаю)

И посмотрите на план выполнения, поиск индекса запланирован [largetable имеет индекс на пользователя], и предполагаемые строки - правильные 29.

Но если я сделаю

select user from largetable where largetable.user = (select user from users where externalid = 100)

[результатом подзапроса является одно значение 1155, как и выше, когда я жестко его кодирую]

Оптимизатор запросов оценивает 117 000 строк в результате. В большой таблице около 6 000 000 строк, 1700 строк в пользователях. Конечно, когда я запускаю запрос, я получаю правильные 29 строк, несмотря на огромные оценочные строки.

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

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

Итак, почему предполагаемый план выполнения показывает такое большое количество предполагаемых строк? Разве оптимизатор не должен знать, основываясь на статистике, что он ищет результат, который имеет 29 соответствующих строк, или МАКСИМАЛЬНОЕ из 3000 строк, даже если он не знает пользователя, который будет выбран подзапросом? Почему эта огромная оценка? Проблема в том, что эта большая оценка затем влияет на другое объединение в более крупном запросе, чтобы выполнить сканирование вместо поиска. Если я выполняю больший запрос с подзапросом, это занимает 1мин 40 секунд. Если запустить его с жестким кодом 1155, это займет 2 секунды. Это очень необычно для меня ...

Спасибо

Chris

Ответы [ 2 ]

1 голос
/ 01 декабря 2010

Оптимизатор делает все возможное, но статистика и подсчет количества строк зашли так далеко (как вы видите).

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

Если это не удастся, настало время использовать ваши дополнительные знания о природе ваших данных, чтобы помочь оптимизатору с подсказками .В частности, посмотрите на параметр forceseek в подсказках index.Обратите внимание, что это может быть плохо, если ваши данные изменятся позже, так что имейте это в виду.

0 голосов
/ 01 декабря 2010

Вы пробовали это?

SELECT lt.user
FROM Users u
     INNER JOIN largeTable lt
        ON u.User = lt.User
WHERE u.externalId = 100

Пожалуйста, смотрите это: subqueries-vs-joins

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