我有一张大桌子的I / O问题。
一般统计
该表具有以下主要特征:
- 环境:Azure SQL数据库(层为P4 Premium(500个DTU))
- 行:2,135,044,521
- 1,275个已使用的分区
- 聚集和分区索引
模型
这是表的实现:
CREATE TABLE [data].[DemoUnitData](
[UnitID] [bigint] NOT NULL,
[Timestamp] [datetime] NOT NULL,
[Value1] [decimal](18, 2) NULL,
[Value2] [decimal](18, 2) NULL,
[Value3] [decimal](18, 2) NULL,
CONSTRAINT [PK_DemoUnitData] PRIMARY KEY CLUSTERED
(
[UnitID] ASC,
[Timestamp] ASC
)
)
GO
ALTER TABLE [data].[DemoUnitData] WITH NOCHECK ADD CONSTRAINT [FK_DemoUnitData_Unit] FOREIGN KEY([UnitID])
REFERENCES [model].[Unit] ([ID])
GO
ALTER TABLE [data].[DemoUnitData] CHECK CONSTRAINT [FK_DemoUnitData_Unit]
GO
分区与此有关:
CREATE PARTITION SCHEME [DailyPartitionSchema] AS PARTITION [DailyPartitionFunction] ALL TO ([PRIMARY])
CREATE PARTITION FUNCTION [DailyPartitionFunction] (datetime) AS RANGE RIGHT
FOR VALUES (N'2017-07-25T00:00:00.000', N'2017-07-26T00:00:00.000', N'2017-07-27T00:00:00.000', ... )
服务质量
我认为索引和统计数据每天晚上都可以通过增量重建/重组/更新得到很好的维护。
这些是最常用的索引分区的当前索引状态:
这些是使用最频繁的分区的当前统计信息属性:
问题
我高频率地对表运行一个简单的查询。
SELECT [UnitID]
,[Timestamp]
,[Value1]
,[Value2]
,[Value3]
FROM [data].[DemoUnitData]
WHERE [UnitID] = 8877 AND [Timestamp] >= '2018-03-01' AND [Timestamp] < '2018-03-13'
OPTION (MAXDOP 1)
执行计划如下所示:https : //www.brentozar.com/pastetheplan/?id=rJvI_4TtG
我的问题是这些查询会产生大量的I / O操作,从而导致PAGEIOLATCH_SH
等待瓶颈。
题
我已经读到,PAGEIOLATCH_SH
等待通常与未优化索引有关。您对我有什么减少I / O操作的建议吗?也许通过添加更好的索引?
答案1-与@ S4V1N的评论有关
发布的查询计划来自我在SSMS中执行的查询。发表您的评论后,我将对服务器历史进行一些研究。从服务执行的准确查询看起来有些不同(与EntityFramework相关)。
(@p__linq__0 bigint,@p__linq__1 datetime2(7),@p__linq__2 datetime2(7))
SELECT 1 AS [C1], [Extent1]
.[Timestamp] AS [Timestamp], [Extent1]
.[Value1] AS [Value1], [Extent1]
.[Value2] AS [Value2], [Extent1]
.[Value3] AS [Value3]
FROM [data].[DemoUnitData] AS [Extent1]
WHERE ([Extent1].[UnitID] = @p__linq__0)
AND ([Extent1].[Timestamp] >= @p__linq__1)
AND ([Extent1].[Timestamp] < @p__linq__2) OPTION (MAXDOP 1)
此外,该计划看起来也不同:
https://www.brentozar.com/pastetheplan/?id=H1fhALpKG
要么
https://www.brentozar.com/pastetheplan/?id=S1DFQvpKz
就像您在这里看到的那样,此查询几乎不会影响我们的数据库性能。
答案2-与@Joe Obbish的答案有关
为了测试解决方案,我用一个简单的SqlCommand替换了Entity Framework。结果是惊人的性能提升!
现在,查询计划与SSMS中的查询计划相同,并且逻辑读取和写入每次执行时下降到〜8。
这也解释了为什么将分区范围从每月更改为每天后,性能会大幅下降。缺少分区消除功能导致需要扫描更多分区。