【发布时间】:2019-07-31 17:49:18
【问题描述】:
我们有 S1:20 DTU 250GB SQL Azure 数据库和下表
CREATE TABLE [dbo].[Reads]
(
[ReadId] [INT] IDENTITY(1,1) NOT NULL,
[LicenseNumber] [VARCHAR](50) NULL,
[Name] [VARCHAR](50) NULL,
[Serial] [VARCHAR](20) NULL,
[FirstSeenUtc] [DATETIME] NULL,
[LastSeenUtc] [DATETIME] NULL,
[Count] [INT] NOT NULL,
[Model] [VARCHAR](100) NULL,
[Make] [VARCHAR](100) NULL,
[TimestampUtc] [DATETIME] NOT NULL,
[PortNumber] [INT] NOT NULL,
[Code] [VARCHAR](50) NULL,
[Peak] [FLOAT] NULL,
CONSTRAINT [PK_Reads]
PRIMARY KEY CLUSTERED ([ReadId] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
这张表有超过8000万行和简单的查询
select count(1) from dbo.Reads
运行时间为 1 小时 30 分钟。数据库上的负载最小,每分钟添加大约 1000 行的进程。目前没有从该表中读取任何内容,并且总体上几乎没有数据库负载。
我将数据库升级到 S2:50 DTU,上面的查询运行了 18 分钟。
我更新了统计数据,但没有太大帮助。我在上面的查询运行时运行了 Brent Ozar 的 BlitzFirst 存储过程,它说数据库正在最大化数据 IO。在我的 Surface 笔记本电脑上恢复的同一数据库会在一秒钟内返回行数。数据库性能选项卡没有任何建议。
S2:50 DTU 每月收费 75 美元,下一个选项是 S3:100 DTU,每月 150 美元。
我的计划是为我注册的每个客户创建一个数据库,但每个数据库每月 150 美元,我很快就会倒闭!
这是 SQL Azure 的预期性能水平吗?这种基本查询不应该立即产生结果吗?迁移到 VM 上的 SQL Server 会更好吗?
[美国东部时间 2019 年 3 月 10 日上午 11:35 更新]
该表确实有以下 IX
CREATE NONCLUSTERED INDEX [IX_Read_License_Code_TimeStamp] ON [dbo].[Reads]
(
[LicenseNumber] ASC,
[Code] ASC,
[TimestampUtc] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
我现在看到一些列可以安全地更改为 NOT NULL 并且可以帮助改进。
[更新:2019-03-10 8:40PM EST]
我更改了表格以使 LicenseNumber 和 Code NOT NULL 花费了 6 个多小时。之后,计数查询在 1 分 32 秒内运行。
以下查询在 40 秒内返回结果
select Code, LicenseNumber, TimeStampUtc from dbo.Reads Where TimestampUtc >= '2019-03-10'
【问题讨论】:
-
尝试在
PortNumber上放置一个索引 - 这是一个不可为空INT列,一旦该索引存在,确定表中的行数应该明显更快。如果您没有这样的索引,那么确定行数基本上意味着进行全表扫描并加载 ALL 数据;在狭窄的、不可为空的列上使用索引,只需加载和检查该索引(数据少得多) -
@marc_s 对
ReadId的PRIMARY KEY约束不会自动索引该字段吗? -
@aaaaaa123456789:是的 - 但 NOT 带有“单列”非聚集索引。主键会自动创建聚集索引——它基本上是整个数据表——而不仅仅是一个
INT列。 -
@marc_s 这很有趣。我的理解和aaaaaa123456789的一样。该表确实有一个非聚集索引(我将添加到原始问题中),当我使用实际查询计划运行计数查询时,它运行了 30 分钟,并显示 92% 的成本是扫描 IX 和剩余的 8 % 是聚合操作。问题是为什么在我的笔记本电脑上恢复的同一个数据库上的相同查询会在一秒钟内返回结果?
-
由于现有索引中的部分(或全部)列可为空,SQL Server 无法使用此索引来计算行数。行的计数发生在索引的 叶级 - 而对于聚集索引,这是整个表数据 -> 因此它很慢。最好的办法是在一个单一的、狭窄的、不可为空的列上建立一个非聚集索引——比如
INT NOT NULL或类似的东西——这将在单个数据页上拥有最多的条目,并且因此扫描整个索引以计算行数将是最快的
标签: sql sql-server azure