Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Domanda sulle prestazioni approfondite di SQL Server HierarchyID

Non è del tutto chiaro se stai cercando di ottimizzare per la ricerca in profondità o in ampiezza; la domanda suggerisce in primo luogo la profondità, ma i commenti alla fine riguardano l'ampiezza.

Hai tutti gli indici di cui hai bisogno per la profondità (basta indicizzare il hierarchyid colonna). Per prima cosa, non è sufficiente creare il level calcolato colonna, devi indicizzarla anche tu:

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

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

(Nota che per gli indici non cluster molto probabilmente avrai bisogno di INCLUDE - in caso contrario, SQL Server potrebbe ricorrere all'esecuzione di una scansione dell'indice in cluster.)

Ora, se stai cercando di trovare tutti gli antenati di un nodo, vuoi prendere una virata leggermente diversa. Puoi effettuare queste ricerche alla velocità della luce, perché - ed ecco cosa c'è di bello in hierarchyid - ogni nodo "contiene" già tutti i suoi antenati.

Uso una funzione CLR per renderlo il più veloce possibile, ma puoi farlo con un CTE ricorsivo:

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

Ora, per ottenere tutti gli antenati e discendenti, usalo in questo modo:

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

Provalo:questo dovrebbe risolvere i tuoi problemi di prestazioni.