我正在尝试执行基于某些参数获取计数的查询。截至目前,该查询所操作的表包含3800万条数据。执行该查询需要6秒。我希望将执行时间缩短到1秒以内,因为我们正在使用结果在Web应用程序上显示。
SELECT Policy id,Policy name, Count(Policy) count
from (SELECT ItemID, OUID, ItemType, ItemGeneratedBy, CreatedDateTime GeneratedDate,
Month, OU Agency FROM ItemMaster) IM
left JOIN (SELECT ItemId, PolicyId FROM ItemPolicy) IP ON IP.ItemId = IM.ItemId
left JOIN (SELECT PolicyId, PolicyName Policy FROM Policies) P ON P.PolicyId = IP.PolicyID
left JOIN (SELECT ItemID, ActualActionStr ActionTaken FROM ItemExtension_McAfee) IEM ON IEM.ItemId = IM.ItemId
left JOIN (SELECT Id, ItemType Channel FROM ItemType) IT ON IT.Id = IM.ItemType
INNER JOIN (SELECT ID, LoginName Violator FROM ItemADUser) IAU ON IAU.ID = IM.ItemGeneratedBy
WHERE IM.OUId is NOT NULL AND Violator = 'sandy' AND ActionTaken='affirm'
AND Policy='dashmagiq network sharing policy' and GeneratedDate >= '2022-06-11 00:00:00'
Group By Policy,Policy Order By Count(Policy) desc
https://drive.google.com/file/d/1y0C6wPW2yXKxxYtbkGcnY4JgkTVJAjdE/view?usp=share_link
上面的链接是这个查询的执行计划,您对如何实现这个目标有什么想法吗?
1条答案
按热度按时间gcuhipw91#
在执行计划中,一个好的起点是
然后,这些问题就成为需要改进的候选问题--通过改进查询和/或更改索引。
对于索引,最好不要只是采纳下面的建议,而是要查看当前的索引和表的使用情况,并检查应该更新和/或添加哪些索引。我在下面的索引中的目标是提供全面覆盖的索引。
作为参考,这里是Paste The Plan link,但我只是在SSMS中查看它。
我认为第一个主要问题是在ItemPolicy和ItemMaster中。这两个似乎都读取了所有行,并且是时间的主要贡献者。基于数据,我建议使用以下索引(注意,为了简单起见,我将它们命名为IX_1、IX_2等)
如果您的查询往往总是在一个很窄的时间范围内,则可以使用上述IX_2的替代方法,在CreatedDateTime上创建索引,例如:
然后是对ItemExtension_McAfee表的完全扫描-该表被标识为缺少索引。
但是,索引建议是另一种方式,因此您可以按相反的顺序尝试
最后,这不会对总时间产生很大影响,但是您完全读取了ItemADUser表以返回一行,并且它使用了LoginName。
如果可能的话,试着加入索引,看看什么在您的情况下运行良好(不仅仅是查询--尝试使用其他过滤选项)。
关于查询本身-似乎没有任何“陷阱”,但为什么要使用子查询,而不只是使用表?例如,而不是
为什么不使用以下方法?
最后-在某个阶段,我会审查你的索引:哪些没有被使用或者只是很少被使用;有两个非常相似的索引,可以合并成一个以及缺少索引的位置(例如,列出的缺少索引,以及正在执行大量聚集索引扫描的表,这些扫描可以通过索引来改进)。