首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >添加条件查询会增加超过2400%的时间。

添加条件查询会增加超过2400%的时间。
EN

Stack Overflow用户
提问于 2016-01-07 18:02:22
回答 1查看 135关注 0票数 5

更新:我会尽快得到查询计划。

我们有一个执行不佳的查询,一个特定的组织花了4分钟。在通常重新编译存储的proc和更新统计信息没有帮助之后,我们重新编写了if存在(.)选择计数(*)..。和存储过程时,从4分钟到70毫秒。使70 ms查询耗时4分钟的条件有什么问题?见示例

这些都需要4+分钟:

代码语言:javascript
复制
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';       

-

代码语言:javascript
复制
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'

所有这些都需要70毫秒:

代码语言:javascript
复制
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';

对于我来说,为什么将完全相同的Count(*)查询移到if语句中会导致这种退化,或者为什么“存在”比Count慢,这对我来说是没有意义的。我甚至在select CASE WHEN Exists()中尝试过select CASE WHEN Exists(),它仍然是4+分钟。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-12 04:29:32

考虑到前面提到的答案,我会再解释一遍,因为这些问题相当棘手。所以是的,我想你看到的问题和另一个问题是一样的。即排目标问题。

因此,为了解释造成这种情况的原因,我将从引擎可用的三种连接类型开始:循环连接、合并连接、哈希连接。循环连接听起来就像在这两组数据上的嵌套循环。合并连接采用两个排序列表,并在锁定步骤中移动它们。Hash加入,将小集合中的所有东西都扔到文件柜中,然后在文件柜填满后在更大的一组中查找项目。

因此,就性能而言,循环联接几乎不需要设置,而且如果您只是在寻找少量数据,它们实际上是最优的。对于任何数据大小,合并都是最好的连接性能最好的,但要求数据已经被排序(这是罕见的)。散列连接需要相当数量的设置,但允许快速连接大型数据集。

现在我们来看看您的查询,以及COUNT(*)EXISTS/TOP 1之间的区别。因此,您所看到的行为是,优化器认为这个查询的行非常有可能(您可以通过规划查询来确认这一点,而不需要分组并查看它认为在最后一步中将得到多少记录)。特别是,它可能认为对于该查询中的某个表,该表中的每条记录都将出现在输出中。

“尤里卡”它说,“如果这个表中的每一行都在输出中结束,为了找出是否存在一个行,我可以在整个过程中进行真正廉价的启动循环连接,因为即使对于大型数据集来说它很慢,但我只需要一行。”但它找不到那一排。再也找不到了。现在,它正在迭代大量的数据,使用最不有效的方法来清除大量的数据。

相比之下,如果您要求完整的数据计数,它必须找到每一个记录的定义。它看到了大量的数据,并选择了最适合迭代整组数据的选择,而不仅仅是其中的一小部分。

另一方面,如果它确实是正确的,并且记录是非常相关的,那么它就会发现您的记录具有尽可能少的服务器资源,并且最大限度地提高了它的总体吞吐量。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34662081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档