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.
Respostas:
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.
fonte