【问题标题】:Slow index performance on SQL Server?SQL Server 上的索引性能慢?
【发布时间】:2021-04-19 18:02:04
【问题描述】:

我有以下查询在 14 秒内运行(这对我来说似乎过多):

select top 20 App.Id
from
    App
    inner join Base on Base.Id = App.BaseId
WHERE    App.TermId = 1190676
ORDER    BY App.Id

apps.Id 是主键 (int)。 Base.Id 是主键 (int)。 App.TermId 和 App.BaseId 是非聚集索引。 App.Term 也是此查询中未使用的表的外键。

Base.Id、App.BaseId 和 App.TermId 上的索引碎片少于 0.5%。

Table Base 有 71,879 条记录,App 有 16,238,898 条记录。如果上面的查询没有顶级条件,则只会返回 796,661。

如果我删除内连接,查询将在不到 1 秒的时间内运行。

我对阅读执行计划了解不多,但似乎寻找索引 Base.Id 的成本最高(70%),但为 0.0s。而聚集索引扫描的成本为 30%,但耗时 18.5 秒。

我已经跑了:

DBCC CHECKTABLE ('dbo.Base', REPAIR_REBUILD)
DBCC CHECKTABLE ('dbo.App', REPAIR_REBUILD)

14 秒听起来合理吗?我还能调查什么?我可以分享执行计划中的其他有用信息吗?

.sqlPlan 可以在这里找到: https://pastebin.com/UxDvsPRk

12:52 我用以下方法进行了测试,上面的查询慢了 1 秒:

CREATE NONCLUSTERED INDEX [ix_dbo_App_TermId_BaseId] ON dbo.App
(
    TermId, BaseId
)

1:14 根据建议,我将索引更新为:

CREATE NONCLUSTERED INDEX [ix_dbo_App_TermId_BaseId] ON dbo.App
(
    TermId, BaseId
)
include (Id)

...查询仍然很慢。但是,现在它似乎只有在 ORDER BY 存在时才会变慢。连接本身不到 1 秒。

【问题讨论】:

  • 你想要ANY 20 的行为吗?您的TOP 不应该与ORDER BY 结合使用以获得可预测的输出吗?执行计划是什么样的(请将 .sqlplan 发布到 pastetheplan.com,而不是图片)?
  • 没有看到计划,对于这个查询,我想App (TermId, Id) 和Base (Id) 上的索引将是最有用的(注意列顺序)。然后你会得到一个非常快速的合并连接
  • @AaronBertrand 我已将 pastebin 添加到我的帖子中。我已经提供了订单。见:pastebin.com/UxDvsPRk
  • 分享计划的更好方法是将计划 XML 上传到 Paste The Plan。这样,图形计划和 XML 都可以轻松查看。
  • 为了澄清@Charlieface 的意思,您需要一个复合索引,一个从 2 列键控出来的索引。他是绝对正确的。您可以通过将 App.TermID 设置为 App.BaseId 索引上的包含列来稍微捏造一下,但我想对此进行测试以确定。

标签: sql-server indexing sql-server-2016


【解决方案1】:

当一个索引中有太多列时,可能会导致索引变慢。首先查看表索引,看看索引键列中有多少列(在索引属性下)。这可能是一个问题。主键列不应该是非聚集索引。外键应该是非集群的。尝试将 Base.ID 上的索引更新为聚集索引。

【讨论】:

  • Base.Id 是一个主键,它是一个聚集索引。我的外键 (App.TermId) 是一个非聚集索引。
  • 当有更好的聚集索引候选者时,可以将主键设置为非聚集索引。这取决于查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 2010-12-04
  • 1970-01-01
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
  • 2013-04-25
相关资源
最近更新 更多