Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server中计数(*)的性能问题_Sql Server_Performance_Count_Aggregate - Fatal编程技术网

Sql server SQL Server中计数(*)的性能问题

Sql server SQL Server中计数(*)的性能问题,sql-server,performance,count,aggregate,Sql Server,Performance,Count,Aggregate,我在SQL Server 2008中运行的查询存在一些性能问题。我有以下疑问: 问题1: SELECT GroupID, COUNT(*) AS TotalRows FROM Table1 INNER JOIN ( SELECT Column1 FROM Table2 WHERE GroupID = @GroupID ) AS Table2 ON Table2.Column1 = Table1.Column1 WHERE CONTAINS(Tabl

我在SQL Server 2008中运行的查询存在一些性能问题。我有以下疑问:

问题1:

 SELECT GroupID, COUNT(*) AS TotalRows FROM Table1 
    INNER JOIN (
        SELECT Column1 FROM Table2 WHERE GroupID = @GroupID
    ) AS Table2
     ON Table2.Column1 = Table1.Column1 
WHERE CONTAINS(Table1.*, @Word) GROUP BY GroupID
表1包含大约500000行。表2包含大约50000个,但最终将包含数百万个。在处理查询时,我发现按如下方式重新编写查询将把查询的执行时间减少到1秒以下

问题2:

SELECT GroupID FROM Table1 
    INNER JOIN (
        SELECT Column1 FROM Table2 WHERE GroupID = @GroupID
    ) AS Table2 ON Table2.Column1 = Table1.Column1 
WHERE CONTAINS(Table1.*, @Word)
我不明白的是,这是一个简单的计数查询。如果我对表1执行以下查询,它将在<1s内返回:

问题3:

SELECT Count(*) FROM Table1
这个查询返回大约500000个结果

但是,上面提到的原始查询(查询1)只返回50000个计数,执行时间为3秒,即使简单地删除GROUP BY(查询2)将执行时间减少到<1秒


我不认为这是一个索引问题,因为我已经在适当的列上建立了索引。任何帮助都将不胜感激。

从表中执行简单的
计数(*)可以更有效地扫描聚集索引,因为它不必关心任何筛选、连接、分组等。包含全文搜索谓词和神秘子查询的查询必须做更多的工作。计数并不是最昂贵的部分-我打赌如果你不计算计数,但将组保留在其中,则计数仍然相对缓慢,例如:

SELECT GroupID FROM Table1 
    INNER JOIN (
        SELECT Column1 FROM Table2 WHERE GroupID = @GroupID
    ) AS Table2 ON Table2.Column1 = Table1.Column1 
WHERE CONTAINS(Table1.*, @Word)
GROUP BY GroupID;
看看in*,我看到了:

这是:

这让我相信你应该:

  • 更新
    Inventory
    A001\u Store\u Inventory
    的统计信息,以便优化器可以获得更好的行数估计(这可能导致更好的计划形状)
  • 确保
    Inventory.ItemNumber
    A001\u Store\u Inventory.ItemNumber
    是相同的数据类型,以避免隐式转换

  • (*)免责声明:我为SQL Sentry工作。

    您应该查看查询计划,看看SQL Server在检索您请求的数据时做了什么。此外,我认为最好将原始查询重写如下:

    SELECT
      Table1.GroupID  -- When you use JOINs, it's always better to specify Table (or Alias) names
      ,COUNT(Table1.GroupID) AS TotalRows
    FROM
      Table1 
      INNER JOIN
      Table2 ON
        (Table2.Column1 = Table1.Column1) AND
        (Table2.GroupID = @GroupID)
    WHERE
      CONTAINS(Table1.*, @Word)
    GROUP BY
      Table1.GroupID
    

    另外,请记住,简单计数和包含JOIN和groupby的计数不是一回事。在一种情况下,只需遍历索引并进行计数,而在另一种情况下,则涉及其他表和分组,这可能会很耗时,具体取决于几个因素。

    SQL Server是否有“解释计划”?是的,有。在Management Studio中,有一个按钮可以单击以查看查询计划。关于这个问题:为什么要从表2中选择列1,其中GroupID=@GroupID
    ,而不是仅仅加入表2?@PaulTomblin我已经查看了执行计划,有趣的是,与查询的其余部分相比,计划的聚合部分的成本非常小。@Diego,过去我通过创建这样的子表在复杂查询中获得了更好的结果。我刚刚测试了这个查询,得到了与OP相同的结果,执行时间约为3秒。我已经检查了执行计划,该计划的计算和聚合部分在整个查询中具有最小的操作员成本。这就是我不明白的。是的,这仍然很慢。只需简单地删除组,即可显著加快速度。知道为什么吗?@ChrisTremblay可能是因为GroupID上没有索引来帮助分组。@ChrisTremblay我不想看到图像。我想查看实际的.sqlplan文件,您可以将其发布到任何不需要下载者登录的文件共享服务。您可以从以下地址下载该文件:@ChrisTremblay我将首先更新A001_Store_库存表的统计信息。我还要确保Inventory.ItemNumber和A001_Store_Inventory.ItemNumber是相同的数据类型(似乎一个是NVARCHAR(15),另一个不是)。