Je travaille avec une procédure stockée qui génère un rang pour tous les nœuds qui sont disponibles dans le tableau SystemTree
.Procédure SQL Server stockée Optimisation requise
Ma procédure stockée fonctionne parfaitement, mais le problème est que l'exécution est trop longue.
Voici les détails de la table:
SystemTree
- 14000+ lignesPaymentSchedule
- 5000+ lignesMasterRankChart
- seulement 15 lignes
je dois optimiser ma procédure stockée . Il faut au moins 20 minutes pour l'exécuter.
Ceci est ma procédure stockée:
ALTER PROCEDURE[dbo].[RankGeneration]
@CreatedUser nvarchar(128),
@CreatedOn datetime
AS
BEGIN
DECLARE @NodeKeyId nvarchar(128)
DECLARE MY_CURSOR CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY FOR
SELECT TOP 1000 NodeKeyId
FROM SystemTree
DECLARE @RankContainer TABLE
(
NodeKeyId nvarchar(128),
[Rank] nvarchar(512),
RankId int,
[LargestLeg] nvarchar(128),
[LargestLegNV] decimal(18, 2),
[SecondLargestLeg] nvarchar(128),
[SecondLargestLegNV] decimal(18, 2),
[ThirdPlusLeg] nvarchar(max),
[ThirdPlusLegNV] decimal(18, 2)
)
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @NodeKeyId
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @YearlyMinPNV bigint
DECLARE @CurrentNodeId nvarchar(128)
DECLARE @TempNodeKeyId nvarchar(128)
DECLARE @TempChildKeyId nvarchar(128)
DECLARE @TempParentKeyId nvarchar(128)
DECLARE @TempPlacementNode hierarchyid
DECLARE @IMMEDIATEIDs TABLE
(
NodeKeyId nvarchar(128),
PlacementNode hierarchyid
)
INSERT INTO @IMMEDIATEIDs
SELECT NodeKeyId, PlacementNode
FROM SystemTree
WHERE PlacementNode.GetAncestor(1) = (SELECT PLACEMENTNODE
FROM SystemTree
WHERE NodeKeyId = @NodeKeyId)
DECLARE @ChildIDs TABLE
(
ParentNodeId nvarchar(128),
NodeKeyId nvarchar(128)
)
DECLARE @FinalNV TABLE
(
ParentNodeId nvarchar(128),
NodeKeyId nvarchar(128),
TotalNV decimal(18, 2)
)
DECLARE @ResultNV TABLE
(
ImmediateNodeID nvarchar(128),
TotalNV decimal(18, 2)
)
DECLARE @StorageNV TABLE
(
NodeKeyId nvarchar(128),
NV decimal(18, 2)
)
INSERT INTO @StorageNV
SELECT NodeKeyId, SUM(NV)
FROM PaymentSchedule
WHERE ClearDate IS NOT NULL
AND NV IS NOT NULL
GROUP BY NodeKeyId
DECLARE @i INT
DECLARE @count INT
SET @i = 0
SELECT @count = COUNT(*)
FROM @IMMEDIATEIDs
WHILE @i < @count
BEGIN
SELECT
@TempNodeKeyId = NodeKeyId,
@TempPlacementNode = PlacementNode
FROM
@IMMEDIATEIDs
ORDER BY
NodeKeyId
OFFSET (@i) ROWS FETCH NEXT 1 ROWS ONLY
INSERT @ChildIDs
SELECT
@TempNodeKeyId AS ParentNodeId,
t.NodeKeyId
FROM SystemTree t
WHERE PlacementNode.IsDescendantOf(@TempPlacementNode) = 1
AND t.NodeKeyId IN (SELECT NodeKeyId
FROM @StorageNV)
SET @i = @i + 1
END
SET @i = 0
SELECT @count = COUNT(*)
FROM @ChildIDs
WHILE @i < @count
BEGIN
SELECT
@TempChildKeyId = NodeKeyId,
@TempParentKeyId = ParentNodeId
FROM
@ChildIDs
ORDER BY
NodeKeyId
OFFSET (@i) ROWS FETCH NEXT 1 ROWS ONLY
INSERT INTO @FinalNV
VALUES(@TempParentKeyId, @TempChildKeyId,
(SELECT SUM(NV)
FROM @StorageNV
WHERE NodeKeyId = @TempChildKeyId));
SET @i = @i + 1
END
INSERT INTO @ResultNV
SELECT ParentNodeId, SUM(TotalNV)
FROM @FinalNV
GROUP BY ParentNodeId
DECLARE @MainCheckResult decimal(18, 2);
DECLARE @LargestLeg nvarchar(128);
DECLARE @MiddleCheckResult decimal(18, 2);
DECLARE @SecondLargestLeg nvarchar(128);
DECLARE @ThirdCheckResult decimal(18, 2);
DECLARE @ThirdPlusLeg nvarchar(128) = NULL;
SET @MainCheckResult = ISNULL((SELECT TOP(1) TotalNV
FROM @ResultNV
ORDER BY TotalNV DESC), 0);
SET @LargestLeg = (SELECT TOP(1) ImmediateNodeID
FROM @ResultNV
ORDER BY TotalNV DESC)
SET @MiddleCheckResult = ISNULL((SELECT TOP(1) TotalNV
FROM @ResultNV
WHERE ImmediateNodeID NOT IN (SELECT TOP(1) ImmediateNodeID
FROM @ResultNV
ORDER BY TotalNV DESC)
ORDER BY TotalNV DESC), 0);
SET @SecondLargestLeg = (SELECT TOP(1) ImmediateNodeID
FROM @ResultNV
WHERE ImmediateNodeID NOT IN (SELECT TOP (1) ImmediateNodeID
FROM @ResultNV
ORDER BY TotalNV DESC)
ORDER BY TotalNV DESC)
SET @ThirdCheckResult = ISNULL((SELECT SUM(TotalNV)
FROM @ResultNV
WHERE ImmediateNodeID NOT IN (SELECT TOP(2) ImmediateNodeID
FROM @ResultNV
ORDER BY TotalNV DESC)), 0);
SET @ThirdPlusLeg = NULL;
INSERT INTO @RankContainer
SELECT TOP(1)
@NodeKeyId AS NodeKeyId,
[Rank],
Id AS RankId,
@LargestLeg AS [LargestLeg],
@MainCheckResult AS [LargestLegNV],
@SecondLargestLeg AS [SecondLargestLeg],
@MiddleCheckResult AS [SecondLargestLegNV],
@ThirdPlusLeg AS [ThirdPlusLeg],
@ThirdCheckResult AS [ThirdPlusLegNV]
FROM
MasterRankChart
WHERE
LargestLegNV + SecondLegNV + ThirdLegNV <= @MainCheckResult + @MiddleCheckResult + @ThirdCheckResult
AND SecondLegNV + ThirdLegNV <= @MiddleCheckResult + @ThirdCheckResult
AND ThirdLegNV <= @ThirdCheckResult
ORDER BY
Priority
FETCH NEXT FROM MY_CURSOR INTO @NodeKeyId
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
MERGE TrackRank AS Target
USING(SELECT
NodeKeyID, [Rank], [RankId],
[LargestLeg], [LargestLegNv],
SecondLargestLeg, SecondLargestLegNV,
ThirdPlusLeg, ThirdPlusLegNV
FROM @RankContainer) AS Source ON (Target.NodeKeyId = Source.NodeKeyId)
WHEN MATCHED THEN
UPDATE
SET Target.[Rank] = Source.[Rank],
Target.[RankId] = Source.[RankId],
Target.[LargestLeg] = Source.[LargestLeg],
Target.[LargestLegNv] = Source.[LargestLegNv],
Target.SecondLargestLeg = Source.SecondLargestLeg,
Target.SecondLargestLegNV = Source.SecondLargestLegNV,
Target.ThirdPlusLeg = Source.ThirdPlusLeg,
Target.ThirdPlusLegNV = Source.ThirdPlusLegNV
WHEN NOT MATCHED BY TARGET THEN
INSERT (NodeKeyId, [Rank], [RankId], LargestLeg, LargestLegNV,
SecondLargestLeg, SecondLargestLegNV,
ThirdPlusLeg, ThirdPlusLegNV,
CreatedOn, UpdatedOn, IsDeleted, CreatedBy)
VALUES (Source.NodeKeyID, Source.[Rank], Source.[RankId],
Source.[LargestLeg], Source.[LargestLegNv],
Source.SecondLargestLeg, Source.SecondLargestLegNV,
Source.ThirdPlusLeg, Source.ThirdPlusLegNV,
@CreatedOn, @CreatedOn, 0, @CreatedUser)
OUTPUT $ACTION, INSERTED.*, DELETED.*;
END
S'il vous plaît jeter un oeil tout me donner des suggestions que comment puis-je optimiser.
Merci & Cordialement,
M. GO
Appréciez vos suggestions, allez certainement travailler dessus. –