Azure SQL 第一次查询慢

Azure SQL slow first query

我们遇到第一次对索引执行查询的速度非常慢。就像索引冷启动一样。 table 很大,有数百万行。

  1. 执行:30+秒
  2. 执行:4 毫秒

数据库脚本:

CREATE TABLE [Audits] (
    [Id] int NOT NULL IDENTITY,
    [Timestamp] datetime2 NOT NULL,
    [PackageUid] nvarchar(450) NOT NULL,
    [DeviceUid] nvarchar(450) NOT NULL,
    CONSTRAINT [PK_Audits] PRIMARY KEY ([Id])
);

CREATE INDEX [IX_Audits_DeviceUid] ON [Audits] ([DeviceUid]);
CREATE INDEX [IX_Audits_PackageUid] ON [Audits] ([PackageUid]);
CREATE INDEX [IX_Audits_Timestamp] ON [Audits] ([Timestamp]);

查询:

SELECT COUNT(*)
FROM [Audits] AS [f]
WHERE [f].[DeviceUid] = "04B6481955104083"
ORDER BY [f].[Timestamp] DESC

SELECT *
FROM [Audits] AS [f]
WHERE [f].[DeviceUid] = "04B6481955104083"
ORDER BY [f].[Timestamp] DESC
OFFSET 1 ROWS FETCH NEXT 10 ONLY

可能的原因:

We are experiencing that the first execution of a query against an index is very slow. It's like there is a cold start of the index. The table is big with millions of rows.

SQL 服务器查询计划总是从内存中的页面缓存中读取数据。如果查询需要一个不在内存中的页面,它会进入 PAGEIOLATCH 等待,同时从磁盘中获取该页面。一旦数据库页面在页面缓存中,它们就会一直留在那里,直到它们通过 LRU-K 页面替换算法被更多 recently/frequently 使用的页面老化。

如果您有大量 WHERE [f].[DeviceUid] = "04B6481955104083" 的行,那么可能需要一些时间才能从 count(*) 的索引中读取所有这些页面。但是所有这些页面可能都适合您的页面缓存,因此下一个 运行 不需要任何物理 IO。

如果您查看实际执行计划,它将具有 CPU、IO 和等待统计信息。

无服务器 Azure SQL 数据库中的内存管理与配置的 VCore 或 DTU 模型(或常规 SQL 服务器)略有不同。

Memory for serverless databases is reclaimed more frequently than for provisioned compute databases. This behavior is important to control costs in serverless and can impact performance.

Serverless Overview - Memory Management

所以在serverless中你会更频繁的处于冷缓存场景。