Než se pustíme do předčasné optimalizace režimu, může být užitečné podívat se do následující šablony dotazu. Pokud nic jiného, toto by mohlo být použito jako základní linie, se kterou lze měřit účinnost možných optimalizací.
SELECT T.Tagid, TagInfo.TagName, COUNT(*)
FROM Items I
JOIN Tags TagInfo ON TagInfo.TagId = T.TagId
JOIN ItemTagMap T ON I.ItemId = T.ItemId
--JOIN ItemTagMap T1 ON I.ItemId = T1.ItemId
WHERE I.ItemId IN
(
SELECT ItemId
FROM Items
WHERE -- Some typical initial search criteria
Title LIKE 'Bug Report%' -- Or some fulltext filter instead...
AND ItemDate > '02/22/2008'
AND Status = 'C'
)
--AND T1.TagId = 'MySql'
GROUP BY T.TagId, TagInfo.TagName
ORDER BY COUNT(*) DESC
Poddotaz je „řídící dotaz“, tj. ten, který odpovídá počátečním kritériím koncového uživatele. (podrobnosti o tom, jak se tento dotaz, který je vyžadován vícekrát, může vejít do celkového optimalizovaného toku, naleznete níže) Komentováno je JOIN na T1 (a možná T2, T3, pokud je vybráno několik značek) a s klauzulí WHERE související kritéria. Ty jsou potřeba, když uživatel vybere konkrétní značku, ať už jako součást počátečního vyhledávání nebo upřesnění. (Může být efektivnější umístit tato spojení a klauzule where v rámci dílčího dotazu; více o nich níže)
Diskuse... "Dotaz na řízení" nebo jeho variace je zapotřebí pro dva různé účely:
-
1 pro poskytnutí úplného seznam ItemId, který je potřeba k výčtu všech přidružených značek.
-
2 pro poskytnutí prvních N hodnot ItemId (N je velikost zobrazené stránky) za účelem vyhledání podrobných informací o položce v tabulce položek.
Všimněte si, že úplný seznam není nutné třídit (nebo může mít prospěch z řazení v jiném pořadí), přičemž druhý seznam je třeba třídit na základě volby uživatele (řekněme podle data, sestupně nebo podle názvu, abecedně vzestupně ). Všimněte si také, že pokud je vyžadováno nějaké pořadí řazení, cena dotazu bude znamenat, že se budete zabývat úplným seznamem (chybí liché optimalizaci samotným SQL a/nebo nějaké denormalizaci, SQL potřebuje „vidět“ poslední záznamy na tomto seznamu , v případě, že patří na vrchol, pokud jde o řazení).
Tato druhá skutečnost je ve prospěch toho, že pro oba účely je stejný dotaz, odpovídající seznam může být uložen v dočasné tabulce. Obecným postupem by bylo rychlé vyhledání horních záznamů N položek s jejich podrobnostmi a jejich okamžité vrácení do aplikace. Aplikace pak může získat ajax-fashion seznam značek pro upřesnění. Tento seznam by byl vytvořen pomocí dotazu podobného tomu výše, kde je poddotaz nahrazen „select * from dočasnéTable“. Pravděpodobnost je dobrá, že se optimalizátor SQL rozhodne tento seznam seřadit (v některých případech), nechme to tak, než abychom to znovu hádali a třídili explicitně.
Dalším bodem, který je třeba zvážit, je možná přenést spojení (spojení) v tabulce ItemTagMap do „dotazu na řízení“, spíše než jak je uvedeno výše. Pravděpodobně je nejlepší tak učinit, a to jak z důvodu výkonu, tak i proto, že vytvoří správný seznam pro účely #2 (zobrazení stránky položek).
Výše popsaný dotaz/tok se pravděpodobně bude škálovat poměrně dobře, dokonce i na relativně skromném hardwaru; předběžně do 1/2 milionu + položek, s trvalým uživatelským vyhledáváním možná až 10 za sekundu. Jedním z klíčových faktorů by byla selektivita počátečních vyhledávacích kritérií.
Nápady na optimalizaci
- [V závislosti na typických případech vyhledávání a na statistikách dat] může mít smysl denormalizovat přenesením (ve skutečnosti duplikováním) některých polí položek do tabulky ItemTagMap. Zejména krátká pole tam mohou být „vítána“.
- Jak data rostou v milionech+ položek, mohli bychom využít typicky silnou korelaci některých značek (např. v SO, PHP často přichází s MySql, mimo jiné často bez dobrého důvodu...), s různými triky. Například zavedení „multi-Tag“ TagId by mohlo trochu zkomplikovat vstupní logiku, ale také by mohlo výrazně snížit velikost mapy.
-- Dost řečí! --
Vhodná architektura a optimalizace by měly být vybrány ve světle skutečných požadavků a efektivního statistického profilu dat...