sql >> Base de Datos >  >> RDS >> Sqlserver

Pregunta sobre el rendimiento en profundidad de SQL Server HierarchyID

No está del todo claro si está intentando optimizar para la búsqueda primero en profundidad o primero en amplitud; la pregunta sugiere primero la profundidad, pero los comentarios al final son acerca de la amplitud.

Tiene todos los índices que necesita para la profundidad primero (solo indexe el hierarchyid columna). En principio, no basta con crear el level calculado columna, tienes que indexarlo también:

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

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

(Tenga en cuenta que para los índices no agrupados, lo más probable es que necesite INCLUDE - de lo contrario, SQL Server puede recurrir a realizar un análisis de índice agrupado en su lugar.)

Ahora, si está tratando de encontrar a todos los ancestros de un nodo, desea tomar un rumbo ligeramente diferente. Puede realizar estas búsquedas a la velocidad del rayo, porque, y esto es lo bueno de hierarchyid - cada nodo ya "contiene" a todos sus ancestros.

Uso una función CLR para hacerlo lo más rápido posible, pero puedes hacerlo con un CTE recursivo:

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

Ahora, para obtener todos los antepasados ​​y descendientes, utilícelo así:

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

Pruébelo:esto debería resolver sus problemas de rendimiento.