Рассмотрим разницу в производительности 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)
Я знаю, что это не красиво, но это единственный способ вызвать правильный план выполнения, если вы используетенасколько я могу судить, структура сущностей.
Большое спасибо за то, что указали мне правильное направление, Мартин!