【问题标题】:Azure sql query is slow when an indexed column used in where clause has a particular value当 where 子句中使用的索引列具有特定值时,Azure sql 查询很慢
【发布时间】:2016-06-26 07:57:34
【问题描述】:

实例:Azure SQL S2 实例 我们有一个包含约 170 万条记录的候选表。候选人表在非主键 AccountID 上建立索引。 AccountID:646 有 80K 行,AccountID:10 有 365K 行。

当我们触发 select top(10) from table where non_pk_indexed_col=int

Select top(10) from candidates where accountid=10

查询以 00:00:00 时间完成

Select top(10) from candidates where accountid=646

,查询以 01:45:00 时间完成

为什么相同的查询值不同时会花费这么长时间

【问题讨论】:

  • 索引碎片怎么办?您是否尝试过重新组织它?
  • 1分45秒的等待类型是什么,你看到内存等待了吗?
  • 我已运行 REORGANIZE,但对性能没有帮助。 @FabrizioAccatino。
  • @gameiswar 我怎么知道等待类型?

标签: sql-server azure azure-sql-database


【解决方案1】:

您很可能会为这两个参数获得非常不同的查询计划。因此,一个性能明显优于另一个。一种检查方法是获取您的实际执行计划并进行检查。

您可以通过按下 SSMS 中的 Include Actual Execution Plan 按钮(执行按钮左侧大约七个)https://msdn.microsoft.com/en-us/library/ms189562.aspx

不过,正如 Neil 所说,您通常会通过更新统计信息来修复糟糕的执行计划。您将希望使用全扫描进行更新,但为了获得最佳结果,您可以通过运行以下查询来做到这一点:

DECLARE @sql nvarchar(MAX);
SELECT @sql = (SELECT 'UPDATE STATISTICS [' + DB_NAME() + '].[' + rtrim(sc.name) + '].[' + rtrim(so.name) + '] WITH FULLSCAN, ALL; '
from sys.sysobjects so
join sys.schemas sc
on so.uid = sc.schema_id
where so.xtype = 'U' 
               FOR XML PATH(''), TYPE).value('.', 'nvarchar(MAX)');
PRINT @sql
EXEC (@sql)

希望对您有所帮助!

【讨论】:

  • 好的,澄清一下表上有 4 个索引。 Index1: PK_Candidate_ID Index2: AccountID Index3: AccountID,LastModified Index4: AccountID,UserID 。实际解释计划指出使用的索引是主键索引而不是 Index2。是不是因为 AccountID 有 3 个索引,所以回退到使用 PK 索引?
  • 带索引的查询提示,修复了问题SELECT TOP (10) * FROM Candidates WITH (INDEX(IDX_Candidate_AccountID)) WHERE AccountID = 646。那么现在问题就变成了,为什么 Index 会被忽略而选择 PK index。
  • 此时,查询编译器如何决定做什么,这往往是一个黑匣子。假设您完成了上面的统计信息更新并且仍然得到错误的计划,您可能不得不坚持查询提示。
  • 我稍后会尝试删除所有索引并仅重新创建一个索引。看看票价如何。但由于我使用的是 ORM(NHibernate),我需要弄清楚如何在其中添加查询提示。
  • 如果您有多个索引在同一列上,我将合并为包含列的单个索引。您将使用更多的存储空间和内存,但您将从涉及的所有查询中获得一致的结果。
【解决方案2】:

我有一个类似的问题,通过运行 exec sp_updatestats 已解决。我必须在复杂查询中的每个表上运行它。我猜其中一张表的查询索引已损坏。

在你的情况下,命令是UPDATE STATISTICS candidates

Thomas LaRock's 文章对此进行了更深入的介绍。

【讨论】:

  • 我运行了UPDATE STATISTICS candidates,但它并没有改变执行时间。我将尝试@cbattlegear 提到的全扫描选项。同样,正如我对下一个答案的评论,MSSQL 正在使用 PrimaryKey 索引而不是带有 AccountID 的索引进行扫描
  • 带索引的查询提示,修复了问题SELECT TOP (10) * FROM Candidates WITH (INDEX(IDX_Candidate_AccountID)) WHERE AccountID = 646。那么现在问题就变成了,为什么 Index 会被忽略而选择 PK index。
猜你喜欢
  • 2022-01-24
  • 2017-02-01
  • 2014-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多