存储过程非常慢
我在查询优化方面遇到了困难,目前我非常接近数据库重新设计的点。 stackoverflow 是我最后的希望。我认为仅仅向您显示查询就足够了,因此我不仅链接了数据库脚本,还链接了数据库备份,以防您不想手动生成数据
在这里您可以找到脚本和备份
当您尝试执行以下操作时,问题就会开始...
exec LockBranches @count=64,@lockedBy='034C0396-5C34-4DDA-8AD5-7E43B373AE5A',@lockedOn='2011-07-01 01:29:43.863',@unlockOn='2011-07-01 01:32:43.863'
主要问题出现在这部分:
UPDATE B
SET B.LockedBy = @lockedBy,
B.LockedOn = @lockedOn,
B.UnlockOn = @unlockOn,
B.Complete = 1
FROM
(
SELECT TOP (@count) B.LockedBy, B.LockedOn, B.UnlockOn, B.Complete
FROM Objectives AS O
INNER JOIN Generations AS G ON G.ObjectiveID = O.ID
INNER JOIN Branches AS B ON B.GenerationID = G.ID
INNER JOIN
(
SELECT SB.BranchID AS BranchID, SUM(X.SuitableProbes) AS SuitableProbes
FROM SpicieBranches AS SB
INNER JOIN Probes AS P ON P.SpicieID = SB.SpicieID
INNER JOIN
(
SELECT P.ID, 1 AS SuitableProbes
FROM Probes AS P
/* ----> */ INNER JOIN Results AS R ON P.ID = R.ProbeID /* SSMS Estimated execution plan says this operation is the roughest */
GROUP BY P.ID
HAVING COUNT(R.ID) > 0
) AS X ON P.ID = X.ID
GROUP BY SB.BranchID
) AS X ON X.BranchID = B.ID
WHERE
(O.Active = 1)
AND (B.Sealed = 0)
AND (B.GenerationNo < O.BranchGenerations)
AND (B.LockedBy IS NULL OR DATEDIFF(SECOND, B.UnlockOn, GETDATE()) > 0)
AND (B.Complete = 1 OR X.SuitableProbes = O.BranchSize * O.EstimateCount * O.ProbeCount)
) AS B
编辑:以下是中的行数每张桌子:
Spicies 71536
Results 10240
Probes 10240
SpicieBranches 4096
Branches 256
Estimates 5
Generations 1
Versions 1
Objectives 1
I have a hard time with query optimization, currently I'm very close to the point of database redesign. And the stackoverflow is my last hope. I don't think that just showing you the query is enough so I've linked not only database script but also attached database backup in case you don't want to generate the data by hand
Here you can find both the script and the backup
The problems start when you try to do the following...
exec LockBranches @count=64,@lockedBy='034C0396-5C34-4DDA-8AD5-7E43B373AE5A',@lockedOn='2011-07-01 01:29:43.863',@unlockOn='2011-07-01 01:32:43.863'
The main problems occur in this part:
UPDATE B
SET B.LockedBy = @lockedBy,
B.LockedOn = @lockedOn,
B.UnlockOn = @unlockOn,
B.Complete = 1
FROM
(
SELECT TOP (@count) B.LockedBy, B.LockedOn, B.UnlockOn, B.Complete
FROM Objectives AS O
INNER JOIN Generations AS G ON G.ObjectiveID = O.ID
INNER JOIN Branches AS B ON B.GenerationID = G.ID
INNER JOIN
(
SELECT SB.BranchID AS BranchID, SUM(X.SuitableProbes) AS SuitableProbes
FROM SpicieBranches AS SB
INNER JOIN Probes AS P ON P.SpicieID = SB.SpicieID
INNER JOIN
(
SELECT P.ID, 1 AS SuitableProbes
FROM Probes AS P
/* ----> */ INNER JOIN Results AS R ON P.ID = R.ProbeID /* SSMS Estimated execution plan says this operation is the roughest */
GROUP BY P.ID
HAVING COUNT(R.ID) > 0
) AS X ON P.ID = X.ID
GROUP BY SB.BranchID
) AS X ON X.BranchID = B.ID
WHERE
(O.Active = 1)
AND (B.Sealed = 0)
AND (B.GenerationNo < O.BranchGenerations)
AND (B.LockedBy IS NULL OR DATEDIFF(SECOND, B.UnlockOn, GETDATE()) > 0)
AND (B.Complete = 1 OR X.SuitableProbes = O.BranchSize * O.EstimateCount * O.ProbeCount)
) AS B
EDIT: Here are the amounts of rows in each table:
Spicies 71536
Results 10240
Probes 10240
SpicieBranches 4096
Branches 256
Estimates 5
Generations 1
Versions 1
Objectives 1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
其他人可能比我能更好地解释为什么这要快得多。经验告诉我,当您有一堆查询在一起运行速度很慢但在各个部分应该很快时,那么值得尝试使用临时表。
这要快得多
平均执行时间为 54 毫秒,而原始执行时间为 6 秒,速度要快得多。
编辑
看看并将我的想法与 RBarryYoung 解决方案中的想法结合起来。如果您使用以下命令创建临时表
,那么您可以将其缩短至 15 毫秒,这比我们开始时的时间快了 400 倍。查看执行计划表明临时表上发生了表扫描。通常,您会尽可能避免表扫描,但对于 128 行(在本例中),它比以前执行的任何操作都要快。
Somebody else might be able to explain better than I can why this is much quicker. Experience tells me when you have a bunch of queries that collectively run slow together but should be quick in their individual parts then its worth trying a temporary table.
This is much quicker
This is much quicker with an average execution time of 54ms compared to 6 seconds with the original one.
EDIT
Had a look and combined my ideas with those from RBarryYoung's solution. If you use the following to create the temporary table
then you can get this down to 15ms which is 400x better than we started with. Looking at the execution plan shows that there is a table scan happening on the temp table. Normally you avoid table scans as best you can but for 128 rows (in this case) it is quicker than whatever it was doing before.
这基本上是一个完整的猜测,但在过去,我发现加入子查询的结果可能会慢得可怕。也就是说,子查询在实际上不需要的时候被评估了太多次。
解决这个问题的方法是将子查询移动到 CTE 中并加入到这些子查询中。祝你好运!
This is basically a complete guess here, but in times past I've found that joining onto the results of a sub-query can be horrifically slow. That is, the subquery was being evaluated way too many times when it really didn't need to.
The way around this was to move the subqueries into CTEs and to join onto those instead. Good luck!
看来两个
uniqueidentifier
列上的连接是问题的根源。一种是聚集索引,另一种是非聚集索引(FK表)。很好的是它们有索引。不幸的是,在连接大量行时,向导的性能非常差。作为故障排除步骤:
It appears the join on the two
uniqueidentifier
columns are the source of the problem. One is a clustered index, the other non-clustered on the (FK table). Good that there are indexes on them. Unfortunately guids are notoriously poor performing when joining with large numbers of rows.As troubleshooting steps:
以下命令在我的系统上运行速度大约是原来的 15 倍:
The following runs about 15x faster on my system:
将子查询插入本地临时表
下面的查询显示与相应表的部分连接而不是完整连接!
Insertion of sub query into local temporary table
The below query shows the partial joins with the corresponding table instead of complete!!