为什么不同的日期时间会根据索引冻结查询?

Sae*_*ati 6 index sql-server

我有一张有十亿条记录的表。它有这些列:

Id bigint,
MobileNumber varchar(100),
Date datetime,
Message nvarchar(400)
Run Code Online (Sandbox Code Playgroud)

它在MobileNumberDate字段上具有非聚集索引。

我想找到 aMobileNumber在指定时期内发送给我们的内容。因此我运行这个查询:

select Message
from ReceivedMessages
where [Date] > 'from-time'
and [Date] < 'to-time'
and MobileNumber = 'number-to-filter'
Run Code Online (Sandbox Code Playgroud)

并且此查询在过去 2 年中以闪电般的速度运行。但是当我将from-time零件更改为更近的日期时,它会冻结并需要 2 分钟以上才能完成。换句话说,基于不同的输入,它的行为也不同,有时甚至会闲逛超过 10 分钟不回来。

我期待一致的行为。我想念索引什么?什么会导致这种不一致的性能?

更新:我更改了列和表的名称,因此无法将执行计划附加为图片。但问题就在这里。谢谢你指导我。

当我更改日期参数的值时,SQL 将索引查找从 更改IX_MobileNumberIX_Date。没想到SQL是根据参数的值来创建执行计划的。那怎么可能?

Ken*_*her 2

你必须记住的是,SQL Server 为每个查询生成一个查询计划。每次生成计划时,它都会考虑您传递给它的值以及表的统计信息。这包括根据您的参数等期望返回多少行。

根据您的编辑,您将根据统计信息获得不同的查询计划。SQL 期望根据您的日期范围返回不同的行数,并据此做出决定(当然还根据 MobileNumber 的统计信息)。

例如,对于日期范围 A,它期望返回 100,000 行中的 10 行。另一方面,MobileNumber 将为您返回 1,000 行。SQL 将使用您的日期索引,然后扫描结果以获取正确的手机号码。

现在,对于日期范围 B,它预计返回 10,000 行,并且 MobileNumber 也返回 1,000 行。现在,更有意义的是首先从 MobileNumber 索引中提取数据,然后扫描该数据以获取正确的日期范围。

一般来说,结合两者的索引可能会做得更好。大概MobileNumber, Date。这样,SQL 不仅可以根据第一部分提取 1,000 行,还可以根据相同的索引快速取回日期信息。