Огромное падение производительности с TOP в SQL Server - PullRequest
5 голосов
/ 07 сентября 2011

Рассмотрим разницу в производительности SQL, когда в первом я выбираю все 26 000 строк, а во втором я просто хочу первые 5.

SELECT tw.*
FROM entity e
JOIN entity_tag et on et.entity_id = e.id
JOIN tag t on t.tag_id = et.tag_id
JOIN tagrelatedtweets trt on trt.FK_Tag_ID = t.tag_id
JOIN tweets tw on tw.PK_Tweet_ID = trt.FK_Tweet_ID
WHERE e.id = 765131
ORDER BY tw.[timestamp]

против

SELECT TOP (5) tw.*
FROM entity e
JOIN entity_tag et on et.entity_id = e.id
JOIN tag t on t.tag_id = et.tag_id
JOIN tagrelatedtweets trt on trt.FK_Tag_ID = t.tag_id
JOIN tweets tw on tw.PK_Tweet_ID = trt.FK_Tweet_ID
WHERE e.id = 765131
ORDER BY tw.[timestamp]

Without: CPU =    201 | Reads:    6880 | Writes:    0 | Duration:   451
With:    CPU = 302439 | Reads: 7453199 | Writes: 3169 | Duration: 74188

Это просто не имеет смысла для меня ... Есть ли другой способ пойти по этому поводу?

После предложения Мартина REBUILD STATISTICS на всех задействованных столах, есть небольшое улучшение, но уловка сизменение суммы TOP в параметр работает лучше всего.

До перестроения статистики:

CPU = 302439 | Reads: 7453199 | Writes: 3169 | Duration: 74188 

После перестроения статистики:

CPU = 127734 | Reads: 4100436 | Writes: 2656 | Duration: 16880 

С параметром:

CPU =    218 | Reads:    6899 | Writes:    0 | Duration:    83 

Запрос с параметром:

DECLARE @TOP INT; SET @TOP=5; 
SELECT TOP (@TOP) tw.*
FROM entity e
JOIN entity_tag et on et.entity_id = e.id
JOIN tag t on t.tag_id = et.tag_id
JOIN tagrelatedtweets trt on trt.FK_Tag_ID = t.tag_id
JOIN tweets tw on tw.PK_Tweet_ID = trt.FK_Tweet_ID
WHERE e.id = 765131
ORDER BY tw.timestamp desc

Последнее замечание для тех из вас, кто использует Entity Framework;если вы испытываете такое поведение, вы можете смоделировать то же поведение на основе параметров, как показано ниже:

.Take(100).ToList().Take(5)

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

Большое спасибо за то, что указали мне правильное направление, Мартин!

1 Ответ

3 голосов
/ 07 сентября 2011

После обсуждения в комментариях кажется, что по какой-то причине план, который SQL Server выбирает для оптимизации для случая «Только первые 5 строк», является субоптимальным.Вероятно, он будет использовать неблокирующие операторы, такие как объединения вложенных циклов, а не блокирующие, такие как хэш-соединения.

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

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

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