Sql server 当where子句中使用的索引列具有特定值时,Azure sql查询速度较慢

Sql server 当where子句中使用的索引列具有特定值时,Azure sql查询速度较慢,sql-server,azure,azure-sql-database,Sql Server,Azure,Azure Sql Database,实例:Azure SQL S2实例 我们有一个候选表,有170万条记录。候选表在非主键AccountID上建立索引。AccountID:646有80K行,AccountID:10有365K行 当我们触发时,从表中选择top(10),其中非索引的列=int Select top(10) from candidates where accountid=10 查询完成时需要00:00:00时间 Select top(10) from candidates where accountid=646 ,

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

当我们触发时,从表中选择top(10),其中非索引的列=int

Select top(10) from candidates where accountid=10
查询完成时需要00:00:00时间

Select top(10) from candidates where accountid=646
,查询完成时将花费01:45:00时间

Select top(10) from candidates where accountid=646

当值不同时,为什么同一个查询会花费如此长的时间

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

在您的情况下,该命令将是
updatestatisticsadidates


这篇文章对此进行了更深入的讨论。

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

您可以通过按下SSMS中的Include Actual Execution Plan(包括实际执行计划)按钮(执行按钮左侧约7个)来完成此操作

正如Neil所说,传统上,你会通过更新统计数据来修正糟糕的执行计划。您将希望使用fullscan进行更新,但为了获得最佳结果,您可以通过运行以下查询:

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)

希望这能有所帮助

那么索引碎片呢?您是否尝试重新组织它?1分45秒的等待类型是什么,您是否看到内存等待?我已运行重新组织,但对性能没有帮助@FabrizioAccatino@gameiswar我怎么知道等待类型?我运行了
updatestatistics-candidates
,但它没有改变执行时间。我将尝试@cbattlegear提到的fullscan选项。同样,正如我对下一个答案所做的评论,MSSQL正在使用PrimaryKey索引而不是AccountID索引作为scanQuery的索引,并通过Index(Index(IDX_Candidate_AccountID))从AccountID=646的候选项中修复问题。现在的问题是,为什么索引被忽略,而PK索引被选择。好的,澄清一下,表中有4个索引。Index1:PK\U候选者\U ID Index2:AccountID Index3:AccountID,上次修改的Index4:AccountID,用户ID。实际解释计划说明使用的索引是主键索引,而不是Index2。是不是因为有3个带有AccountID的索引,它又回到了使用PK索引的状态?带有索引的查询提示修复了问题
从带有(index(IDX\u Candidate\u AccountID))的候选项中选择TOP(10)*,其中AccountID=646
。现在的问题是,为什么索引会被忽略,而PK索引会被选择。在这一点上,问题变成了查询编译器如何决定要做什么,这往往是一个黑匣子。假设您完成了上面的统计数据更新,但仍然得到了错误的计划,那么您可能必须坚持使用查询提示。稍后我将尝试删除所有索引并仅重新创建一个索引。看看情况如何。但是,由于我使用的是ORM(NHibernate),我需要弄清楚如何在其中添加查询提示。如果在同一列上键入了多个索引,我将合并为包含列的单个索引。您将使用更多的存储和内存,但您将从所有涉及的查询中获得一致的结果。