sql >> Databáze >  >> RDS >> Sqlserver

Otázka o výkonu SQL Server HierarchyID na prvním místě

Není zcela jasné, zda se snažíte optimalizovat pro vyhledávání do hloubky nebo do šířky; otázka naznačuje nejprve hloubku, ale komentáře na konci jsou o šířce.

Máte všechny indexy, které potřebujete pro hloubku na prvním místě (stačí indexovat hierarchyid sloupec). Pokud jde o šířku, nestačí jen vytvářet vypočítanou level musíte také indexovat:

ALTER TABLE Message
ADD [Level] AS MessageID.GetLevel()

CREATE INDEX IX_Message_BreadthFirst
ON Message (Level, MessageID)
INCLUDE (...)

(Uvědomte si, že pro indexy bez klastrů budete s největší pravděpodobností potřebovat INCLUDE - V opačném případě se SQL Server může uchýlit k provedení skenování clusterového indexu.)

Nyní, pokud se snažíte najít všechny předky uzlu, chcete zvolit trochu jiný směr. Tato vyhledávání můžete provést bleskově, protože – a zde je to, co je skvělé na hierarchyid - každý uzel již "obsahuje" všechny své předky.

Používám funkci CLR, abych to udělal co nejrychleji, ale můžete to udělat pomocí rekurzivního CTE:

CREATE FUNCTION dbo.GetAncestors
(
    @h hierarchyid
)
RETURNS TABLE
AS RETURN
WITH Hierarchy_CTE AS
(
    SELECT @h AS id

    UNION ALL

    SELECT h.id.GetAncestor(1)
    FROM Hierarchy_CTE h
    WHERE h.id <> hierarchyid::GetRoot()
)
SELECT id FROM Hierarchy_CTE

Nyní, abyste získali všechny předky a potomky, použijte to takto:

DECLARE @MessageID hierarchyID   /* passed in from application */

SELECT m.MessageID, m.MessageComment 
FROM Message as m
WHERE m.MessageId.IsDescendantOf(@MessageID) = 1
OR m.MessageId IN (SELECT id FROM dbo.GetAncestors(@MessageID.GetAncestor(1)))
ORDER BY m.MessageID

Vyzkoušejte to – to by mělo vyřešit vaše problémy s výkonem.



  1. MySQL - počítání po měsíci (včetně chybějících záznamů)

  2. MySQL - Načte hodnotu řádku z jiné tabulky v závislosti na hodnotě řádku v tabulce

  3. Java - datum uložené jako předchozí den

  4. AbstractMethodError na resultset.getObject