Desempenho CTE recursivo

8

Precisa de ajuda com o desempenho recursivo do CTE. Abaixo, o CTE está executando muito lentamente, pois está tentando extrair dados heirárquicos de forma recusativa. A tabela é grande, com todos os IDs de raiz com até 3 itensid recursivos. Pode haver cerca de 200000 ou mais IDs de raiz. Eu sei que as CTEs recursivas são lentas para um conjunto de dados enorme, pois para cada rootid ancorado, seria itemid recursivamente.

Esquema:

Create table RootItem (ItemId int primary key, RootIt int , insertdate datetime)

A tabela acima tem mais de 1 milhão de linhas.

Consulta CTE:

; With rootcte as

( select itemid from RootItem where rootid is null

union all

  select r.itemid as RootId , i.itemid from RootItem i join rootcte r
    on i.rootid = r.itemid
)

Não podemos modificar o esquema da tabela e usar heirarchyid. Eu tentei loop enquanto também, mas isso é lento também.

Existe alguma outra maneira de otimizar esta consulta?

 ; With rootcte as

( select itemid from RootItem where rootid is null

 union all

 select r.itemid as RootId , i.itemid from RootItem i join rootcte r
 on i.rootid = r.itemid
) 
  SELECT  
     Cust.CustomerID  
    , Cust.BusinessName  
    , sCust.RegionCustomerID  
    , ord.OrderID  
    , ord.OrderItemID  
    , prd.ProductCode  
    , rc.itemid
    , rc.rootid 
    , mf.FileID  
FROM  
    vw_Customer Cust  
    INNER JOIN SrcCustomer scust ON Cust.CustomerID = sCust.RegionCustomerID  
    INNER JOIN OrderItem ord ON Cust.MasterCustomerID = ord.MasterCustomerID  
    INNER JOIN Product ON ord.ProductID = Product.ProductID  
    INNER JOIN rootcte rc ON ord.RootOrderId = rc.Rootid   
    INNER JOIN MFolder mf ON mf.mfolderid = rc.itemid  
    INNER JOIN MVersion mv ON mv.mfolderversionid = mf.mfolderid   
    WHERE ord.IsActive = 1  and product.IsSelling = 1 and mf.fileid in (23,45,29)
     and mv.isdeleted = 'N' 

Também estou trabalhando com o grupo de BI para alterar a lógica da consulta e filtrar dados no próprio cte de mover algumas junções e critérios para cte. Obrigado por todos os comentários.

njvds
fonte
2
por que você precisa de todas as hierarquias? NÃO deve haver um local onde esteja em algum lugar, para que você calcule apenas os registros que pretende usar. Certamente você não precisa construir milhões de hierarquias toda vez que executar isso.
HLGEM
Este é um relatório colateral que é executado em torno de 5 a 6 vezes em um horário comercial e precisa ser executado em um conjunto de dados inteiro. Eu poderia pré-carregar os dados se os dados fossem estáticos ou não fossem inseridos com frequência, mas nesse caso operações DML frequentes estão sendo executadas nesta tabela no DB.
Njvds
Quais índices você possui nesta tabela?
precisa saber é o seguinte
ItemID é a chave primária e também existe um índice não clusterizado no itemid e no rootid.
Njvds
11
Você precisa mostrar a consulta que está realmente usando. No momento, tudo o que você faz é uma maneira complicada de retornar todo o ItemID da tabela. O CTE recursivo não adiciona nenhum valor.
Mikael Eriksson

Respostas:

3

Você diz que a hierarquia é modificada. Presumivelmente enquanto esta operação está em execução, há alguma quantidade de bloqueio que está ocorrendo então?

Mesmo que a hierarquia esteja mudando, as raízes dos itens estão mudando?

Você já olhou o tempo necessário para fazer a tabela de mapeamento da raiz para o item e indexá-la?

Gostaria de ver o plano de execução para ver o que está acontecendo - o CTE deve ser colocado em spool, mas como uma tabela manualmente materializada e indexada, ele pode ter um desempenho melhor nas etapas posteriores.

Mesmo com atividades pesadas, parece-me que alguém precisa ser bloqueado se as operações DML estiverem alterando os dados que esse processo está lendo.

Então, eu consideraria fortemente tirar um instantâneo da hierarquia.

Além disso, você tem vários outros JOINs INTERNOS - você deve revisar se, de fato, são os CTEs e se há algum índice ausente para tornar essas junções eficazes. O plano de execução deve lhe dizer isso.

Você parece ter muitas coisas na cláusula WHERE que podem ajudar a reduzir algumas operações (e determinar quais índices podem ser os melhores)), mas é difícil saber sem examinar o plano de execução ou os índices.

Cade Roux
fonte
Por que uma operação DML bloqueia o SELECT? O SQL Server ainda é tão limitado?
a_horse_with_no_name
@a_horse_with_no_name msdn.microsoft.com/en-us/library/ms173763.aspx é possível, mas o usuário mencionados há alta atividade, então ele precisa considerar sua estratégia
Cade Roux