更新:我会尽快得到查询计划.
我们的查询效果不佳,需要4分钟才能完成特定组织.在通常的重新编译之后,存储的proc和更新统计信息没有帮助,我们将if Exists(...)重写为select count(*)...以及4分钟到70毫秒的存储过程.条件使得70毫秒查询需要4分钟的问题是什么?查看示例
这些都需要4分钟以上:
if (
SELECT COUNT(*)
FROM ObservationOrganism omo
JOIN Observation om ON om.ObservationID = omo.ObservationMicID
JOIN Organism o ON o.OrganismID = omo.OrganismID
JOIN ObservationMicDrug omd ON omd.ObservationOrganismID = omo.ObservationOrganismID
JOIN SIRN srn ON srn.SIRNID = omd.SIRNID
JOIN OrganismDrug od ON od.OrganismDrugID = omd.OrganismDrugID
WHERE
om.StatusCode IN ('F', 'C')
AND o.OrganismGroupID <> -1
AND od.OrganismDrugGroupID <> -1
AND (om.LabType <> 'screen' OR om.LabType IS NULL)) > 0
print 'records';
Run Code Online (Sandbox Code Playgroud)
-
IF (EXISTS(
SELECT *
FROM ObservationOrganism omo
JOIN Observation om ON om.ObservationID = omo.ObservationMicID
JOIN Organism o ON o.OrganismID = omo.OrganismID
JOIN ObservationMicDrug omd ON omd.ObservationOrganismID = omo.ObservationOrganismID
JOIN SIRN srn ON srn.SIRNID = omd.SIRNID
JOIN OrganismDrug od ON od.OrganismDrugID = omd.OrganismDrugID
WHERE
om.StatusCode IN ('F', 'C')
AND o.OrganismGroupID <> -1
AND od.OrganismDrugGroupID <> -1
AND (om.LabType <> 'screen' OR om.LabType IS NULL))
print 'records'
Run Code Online (Sandbox Code Playgroud)
这一切都需要70毫秒:
Declare @recordCount INT;
SELECT @recordCount = COUNT(*)
FROM ObservationOrganism omo
JOIN Observation om ON om.ObservationID = omo.ObservationMicID
JOIN Organism o ON o.OrganismID = omo.OrganismID
JOIN ObservationMicDrug omd ON omd.ObservationOrganismID = omo.ObservationOrganismID
JOIN SIRN srn ON srn.SIRNID = omd.SIRNID
JOIN OrganismDrug od ON od.OrganismDrugID = omd.OrganismDrugID
WHERE
om.StatusCode IN ('F', 'C')
AND o.OrganismGroupID <> -1
AND od.OrganismDrugGroupID <> -1
AND (om.LabType <> 'screen' OR om.LabType IS NULL);
IF(@recordCount > 0)
print 'records';
Run Code Online (Sandbox Code Playgroud)
对我来说,为什么将完全相同的Count(*)查询移动到if语句会导致这种降级或者为什么'Exists'慢于Count.我甚至尝试过exists()a select CASE WHEN Exists(),它仍然是4分钟以上.
小智 4
鉴于提到了我之前的答案,我将尝试再次解释,因为这些事情非常棘手。所以是的,我认为您看到了与另一个问题相同的问题。即行目标问题。
因此,为了尝试解释导致此问题的原因,我将从引擎可以使用的三种类型的联接开始(并且几乎是明确的):循环联接、合并联接、哈希联接。循环连接顾名思义,是两组数据上的嵌套循环。合并连接采用两个排序列表并以锁定步骤在它们之间移动。散列连接将较小集合中的所有内容放入文件柜中,然后在文件柜装满后查找较大集合中的项目。
因此,就性能而言,循环连接几乎不需要任何设置,如果您只寻找少量数据,它们确实是最佳选择。就任何数据大小的连接性能而言,合并是最好的,但要求数据已经排序(这种情况很少见)。哈希连接需要大量的设置,但允许快速连接大型数据集。
COUNT(*)现在我们来了解您的查询以及和之间的区别EXISTS/TOP 1。因此,您看到的行为是优化器认为此查询的行确实很可能(您可以通过规划查询而不进行分组并查看它认为在最后一步中将获得多少记录来确认这一点)。特别是,它可能认为对于该查询中的某个表,该表中的每条记录都会出现在输出中。
“尤里卡!” 它说,“如果此表中的每一行最终都出现在输出中,为了查找是否存在,我可以在整个过程中进行非常便宜的启动循环连接,因为即使对于大型数据集来说速度很慢,但我只需要一行。” 但随后它找不到该行。并且再也找不到了。现在,它正在使用现有的效率最低的方法来迭代大量数据,以清除大量数据。
相比之下,如果您要求完整的数据计数,它必须根据定义找到每条记录。它看到大量数据,并选择最适合迭代整个数据集而不是其中一小部分的选择。
另一方面,如果它确实是正确的并且记录非常相关,那么它就会以尽可能少的服务器资源找到您的记录,并最大化其整体吞吐量。
| 归档时间: |
|
| 查看次数: |
122 次 |
| 最近记录: |