【问题标题】:Simple WHERE clause kills my query's performance简单的 WHERE 子句会破坏我的查询性能
【发布时间】:2012-09-14 17:17:02
【问题描述】:

我在查询时遇到了这个奇怪的性能问题,我正试图弄清楚为什么会发生这种情况。这是查询的简化示例:

SELECT DISTINCT table1.status AS Status
FROM table1
INNER JOIN (
        SELECT DataID, MAX(VersionNum) as mVersion 
        FROM table1
        GROUP BY DataID 
    ) AS b 
    ON table1.DataID = b.DataID 
    AND table1.VersionNum = b.mVersion
INNER JOIN table2
    ON table1.table2ID = table2.ID
WHERE table2.field = @parameter

表 1 由有时具有相同 DataID 的行组成,这些行都有一个版本号,我需要从那组行中选择最高的数字。

表 1 包含某个 ID,可用于与 table2 连接。 如果我从 table2 添加约束并且参数实际存在于 table2 中,则查询需要一分钟才能完成,返回 10 行。

如果我为 table1 添加约束,则不会出现任何性能问题,只需不到一秒钟即可完成。

我希望这是足够的信息,我真的很好奇为什么会发生这种情况以及如何解决它。

编辑:我必须提到,如果我删除第一个内部连接(过滤最大版本),性能下降就消失了。

【问题讨论】:

  • 你有没有索引,如果有,它们到底是什么?
  • 那么,您使用的是 MySQL 还是 SQL Server?
  • table2.field的数据类型是什么,%Parameter%的值是什么?
  • 对于 table2,如果我为新窗口创建索引,它会返回:CREATE NONCLUSTERED INDEX [table2_Index1] ON [table2] ([VolumeID] ASC, [DataID] ASC, [VersionNum] ASC, [Seq] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] Microsoft SQL Server
  • table2.field 为 INT,值为 6 位数字

标签: sql-server


【解决方案1】:

我知道分析器应该能够处理所有这些情况,但我还是要问...

您是否尝试过分析以下任何一项:

  • 将内部选择转换为 CTE?
  WITH CTE_Versions AS (
      SELECT DataID, MAX(VersionNum) as mVersion 
      FROM t1
      GROUP BY DataID 
  )
  SELECT DISTINCT t1.status AS Status
  FROM t1
  JOIN CTE_Versions AS b
      ON t1.DataID = b.DataID 
      AND t1.VersionNum = b.mVersion
  JOIN table2
      ON t1.table2ID = table2.ID
  WHERE table2.field = @parameter
  • 添加锁定提示?
  SELECT DISTINCT t1.status AS Status
  FROM t1 with (nolock)
  JOIN (
          SELECT DataID, MAX(VersionNum) as mVersion 
          FROM t1 with (nolock)
          GROUP BY DataID 
  ) AS b
      ON t1.DataID = b.DataID 
      AND t1.VersionNum = b.mVersion
  JOIN table2 with (nolock)
      ON t1.table2ID = table2.ID
  WHERE table2.field = @parameter
  • 将参数移动到连接中? (根据@X-Zero 的评论)
  SELECT DISTINCT t1.status AS Status
  FROM t1
  JOIN (
          SELECT DataID, MAX(VersionNum) as mVersion 
          FROM t1
          GROUP BY DataID 
  ) AS b
      ON  t1.DataID = b.DataID 
      AND t1.VersionNum = b.mVersion
  JOIN table2
      ON  t1.table2ID = table2.ID
      AND table2.field = @parameter

我很想知道这三个(或它们的组合)会如何发展?

【讨论】:

    猜你喜欢
    • 2014-06-11
    • 2012-06-11
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多