0

我在 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 包含大约 500,000 行。Table2 包含大约 50,000 个,但最终将包含数百万个。玩弄查询,我发现按如下方式重写查询会将查询的执行时间减少到 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 执行以下查询,它会在 < 1 秒内返回:

查询 3:

SELECT Count(*) FROM Table1

此查询返回大约 500,000 作为结果。

但是,上面提到的原始查询(查询 1)仅返回 50,000 的计数并且执行需要 3 秒,即使简单地删除 GROUP BY(查询 2)将执行时间减少到 < 1 秒。

我不认为这是一个索引问题,因为我已经在相应的列上有了索引。任何帮助将不胜感激。

4

2 回答 2

0

执行一个简单的COUNT(*) FROM table可以对聚集索引进行更有效的扫描,因为它不必关心任何过滤、连接、分组等。包括全文搜索谓词和神秘子查询的查询必须做很多事情更多的工作。计数不是那里最昂贵的部分 - 我敢打赌,如果您将计数排除在外,但将分组留在内部,它们仍然相对较慢,例如:

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;

查看免费的 SQL Sentry Plan Explorer *中提供的实际执行计划,我看到:

在此处输入图像描述

还有这个:

在此处输入图像描述

这让我相信你应该:

  1. 更新两者的统计信息InventoryA001_Store_Inventory以便优化器可以获得更好的行数估计(这可能会导致更好的计划形状)。
  2. 确保Inventory.ItemNumberA001_Store_Inventory.ItemNumber是相同的数据类型以避免隐式转换。

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

于 2012-08-01T15:20:39.950 回答
0

您应该查看查询计划以了解 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

另外,请记住,简单的 COUNT 和带有 JOIN 和 GROUP BY 的 COUNT 不是一回事。在一种情况下,这只是通过索引并进行计数的问题,在另一种情况下,还涉及其他表和分组,这可能会很耗时,具体取决于几个因素。

于 2012-08-01T15:20:45.563 回答