2011-04-22 15 views
5

Tengo una tabla con auto unión. Puede pensar en la estructura como una tabla estándar para representar la jerarquía organizacional. Ej tabla: -Optimización de CTE para consultas recursivas

MemberId 
MemberName 
RelatedMemberId 

Esta tabla consiste en 50000 registros de muestras. Escribí una consulta recursiva CTE y funciona absolutamente bien. Sin embargo, el tiempo que lleva procesar solo 50000 registros es de alrededor de 3 minutos en mi máquina (4GB Ram, 2.4 Ghz Core2Duo, 7200 RPM HDD).

¿Cómo puedo posiblemente mejorar el rendimiento porque 50000 no es un número tan grande? Con el tiempo, seguirá aumentando. Esta es la consulta que es exactamente lo que tengo en mi Procedimiento almacenado. El propósito de la consulta es seleccionar todos los miembros que pertenecen a un miembro específico. P.ej. Debajo de Propietario de la compañía viene cada persona. Para el administrador, excepto el propietario, se devuelven todos los registros. Espero que entiendas el propósito de la consulta.

ANSI_NULLS SET en GO QUOTED SET EN GO

Alter PROCEDURE spGetNonVirtualizedData 
(
    @MemberId int 
) 
AS 
BEGIN 

    With MembersCTE As 
    (
     Select parent.MemberId As MemberId, 0 as Level 
      From Members as parent Where IsNull(MemberId,0) = IsNull(@MemberId,0) 

        Union ALL 
     Select child.MemberId As MemberId , Level + 1 as Level 
      From Members as child 
       Inner Join MembersCTE on MembersCTE.MemberId = child.RelatedMemberId 
    ) 
    Select Members.* 
     From MembersCTE 
     Inner Join Members On MembersCTE.MemberId = Members.MemberId 
     option(maxrecursion 0) 

END 
GO 

Como se puede ver a mejorar el rendimiento, incluso he hecho las uniones en el último paso durante la selección de registros para que todos los registros innecesarios hacen no se inserta en la tabla de temp. Si hice uniones en mi paso base y en el paso recursivo de CTE (en lugar de Seleccionar en el último paso) ¡la consulta tarda 20 minutos en ejecutarse!

MemberId es la clave principal de la tabla.

Gracias de antemano :)

Respuesta

8

En su condición de anclaje que tiene Where IsNull(MemberId,0) = IsNull(@MemberId,0) Supongo que esto es sólo porque cuando se pasa como un parámetro NULL= no funciona en términos de traer de vuelta IS NULL valores. Esto causará un escaneo en lugar de una búsqueda.

Use WHERE MemberId = @MemberId OR (@MemberId IS NULL AND MemberId IS NULL) en lugar de es sargable.

También asumo que no puede tener un índice en RelatedMemberId. Si no se debe añadir una

CREATE NONCLUSTERED INDEX ix_name ON Members(RelatedMemberId) INCLUDE (MemberId) 

(aunque se puede omitir el bit de columna incluida si MemberId es la clave del índice agrupado, ya que será incluida automáticamente)