sql >> Databasteknik >  >> RDS >> Sqlserver

Fråga om SQL Server HierarchyID depth-first performance

Det är inte helt klart om du försöker optimera för djup-först eller bredd-först sökning; frågan antyder djupet först, men kommentarerna i slutet handlar om bredden först.

Du har alla index du behöver för depth-first (indexera bara hierarchyid kolumn). För bredd-först räcker det inte bara att skapa den beräknade level kolumn, måste du indexera den också:

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

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

(Observera att för icke-klustrade index kommer du sannolikt att behöva INCLUDE - annars kan SQL Server tillgripa att göra en klustrad indexsökning istället.)

Nu, om du försöker hitta alla förfäder av en nod vill du ta ett lite annorlunda grepp. Du kan göra dessa sökningar blixtsnabbt, eftersom - och här är vad som är coolt med hierarchyid - varje nod "innehåller" redan alla sina förfäder.

Jag använder en CLR-funktion för att göra detta så snabbt som möjligt, men du kan göra det med en rekursiv 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

Nu, för att få alla förfäder och ättlingar, använd det så här:

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

Testa det - det här borde lösa dina prestandaproblem.



  1. xml till oracle DB-tabell:stöter på problem

  2. Är det möjligt att ha en MySQL-kolumn som innehåller flera värden som främmande nycklar?

  3. node-postgres $1 ÄR NULL-fel

  4. Spara kontoinformationen i alla aktiviteter i android studio