큰 테이블에 I / O 문제가 있습니다.
일반 통계
이 표에는 다음과 같은 주요 특징이 있습니다.
- 환경 : Azure SQL Database (계층은 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
여기에서 볼 수 있듯이이 쿼리는 DB 성능에 거의 영향을 미치지 않습니다.
답변 2-@Joe Obbish의 답변과 관련 있음
솔루션을 테스트하기 위해 Entity Framework를 간단한 SqlCommand로 대체했습니다. 결과는 놀라운 성능 향상이었습니다!
쿼리 계획은 이제 SSMS와 동일하며 논리적 읽기 및 쓰기는 실행 당 ~ 8로 떨어집니다.
또한 파티션 범위를 월 단위에서 일 단위로 변경 한 후 성능이 크게 저하되는 이유에 대해서도 설명합니다. 파티션 제거가 누락되면 더 많은 파티션을 스캔 할 수 있습니다.