【问题标题】:SQL Server: How can a table scan be so expensive on a tiny table?SQL Server:如何在一个小表上进行表扫描如此昂贵?
【发布时间】:2011-03-27 08:34:09
【问题描述】:

我正在查看一个麻烦查询的执行计划。

我可以看到 45% 的计划用于对包含七 (7) 行数据的表进行表扫描。

我即将在一个有七行的表上放置一个聚集索引来覆盖我的查询中的列,但感觉……错了。鉴于表如此之小,我的查询的这一部分如何占用这么多计划?

我正在阅读here,感觉这可能只是因为数据不连续 - 有问题的表上根本没有索引。总的来说,尽管我们的数据库很大(7GB)而且很忙。

我很想知道其他人的想法 - 谢谢!

编辑:

查询非常频繁地运行并且涉及死锁(并被选为受害者)。现在运行需要 300 毫秒到 500 毫秒,但是当数据库更忙时会花费更长的时间。

查询:

select l.team1Score, l.team2Score, ls.team1ExternalID, ls.team2ExternalID, et.eventCategoryID, e.eventID, ls.statusCode 
from livescoretracking l(nolock) 
inner join liveScores ls (nolock) on l.liveScoreID = ls.liveScoreID 
inner join db1.dbo.events e on e.gameid = ls.gameid 
inner join db1.dbo.eventtype et (nolock) on e.eventTypeID = et.eventTypeID 
inner join eventCategoryPayTypeMappings ecb (nolock) on ( et.eventCategoryID = ecb.eventCategoryID and e.payTypeID = ecb.payTypeID and ecb.mainEvent = 1 ) 
where ls.gameID = 286711 order by l.dateinserted

问题表是 eventCategoryPayTypeMappings 表 - 谢谢!

【问题讨论】:

  • 如果查询运行速度很快,那么 45% 不是问题。查询需要多长时间?
  • 你写信给桌子吗?如果你做,多少钱?您是否有大列,例如 blob?
  • @Albin - 表不会增长,我们没有任何 BLOB/CLOB 数据类型。
  • 我注意到您的查询中使用了db1.dbo。这是否意味着这些表与其他表不在同一个数据库中,或者是从链接服务器调用的?
  • @Thomas - 确实,它们是跨数据库连接。

标签: sql optimization sql-server-2000 performance


【解决方案1】:

这实际上取决于查询从开始到结束需要多长时间。如果查询只需要 10 毫秒,45% 并不意味着它需要很长时间。它真正说的是大部分时间都花在了可以理解的表扫描上。

当表增长时,拥有索引可能会有所帮助,并且可能不是一个坏主意,除非您知道该表不会增长。但是,您会发现向具有 7 条记录的表添加索引对性能几乎没有影响。

【讨论】:

    【解决方案2】:

    对七行表的表扫描并不昂贵。除非有查询提示,否则无论存在什么索引,查询引擎都会对这么小的表使用表扫描。您能否向我们展示更多有关查询和执行计划问题的信息?

    【讨论】:

      【解决方案3】:

      如果不知道实际的总成本,百分比成本是没有意义的。例如如果查询需要 1 毫秒来执行表扫描的 45% 成本是 0.45 毫秒,这不值得尝试优化,如果查询需要 10 秒来执行,那么 45% 的成本是显着的,值得优化。

      【讨论】:

      • 对小表进行表扫描是否比在小表上使用索引更快,只是出于兴趣?
      • 我添加了上面的时间。这是最好的案例时间。
      • @Pure.Krome - 是的。在某个阈值之前,您将始终对小表进行扫描。
      • 你如何找到总成本?
      【解决方案4】:

      如果表上没有索引,查询引擎将总是必须进行表扫描。它没有其他方法可以处理数据。

      即使有个索引,许多 RDBMS 平台也会对那么小的表进行表扫描。 (我不确定 SQL Server 的具体情况。)

      我会更关心查询计划中的实际数字。

      【讨论】:

      • @Thansk Toby - 我担心计划中的数字 - 45% 对于计划的一部分加入 4 张桌子来说是一个很大的数字...
      【解决方案5】:

      对小表进行表扫描并不是一件坏事——如果它适合单次读取缓存,优化器将计算出表扫描的成本低于通过索引链读取。

      如果您想帮助确保内容将“倾向于”以这种方式排序,我只会推荐一个聚集索引(尽管您需要明确的 order by 来保证这一点)。

      【讨论】:

        【解决方案6】:

        死锁通常更能说明资源访问顺序问题,而不是查询设计问题。我会查看死锁中的其他参与者,并查看每个事务锁定的其他对象需要哪些对象。如果您可以重新排序以确保访问顺序一致,则可以完全避免争用问题。

        【讨论】:

        • 我听说你从迈克那里来,我刚决定看一下计划并注意到了这一点。
        猜你喜欢
        • 2022-01-16
        • 2019-12-08
        • 2021-10-09
        • 1970-01-01
        • 1970-01-01
        • 2019-11-06
        • 2020-07-07
        • 1970-01-01
        • 2016-02-03
        相关资源
        最近更新 更多