Tôi có một vấn đề I / O với một bảng lớn.
Thống kê chung
Bảng có các đặc điểm chính sau:
- môi trường: Cơ sở dữ liệu Azure SQL (tầng là P4 Premium (500 DTU))
- hàng: 2.135.044.521
- 1.275 phân vùng đã sử dụng
- chỉ mục phân cụm và phân vùng
Mô hình
Đây là bảng thực hiện:
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
Việc phân vùng có liên quan đến điều này:
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', ... )
Chất lượng dịch vụ
Tôi nghĩ rằng các chỉ số và số liệu thống kê được duy trì tốt mỗi đêm bằng cách xây dựng lại / sắp xếp lại / cập nhật gia tăng.
Đây là các số liệu thống kê chỉ mục hiện tại của các phân vùng chỉ mục được sử dụng nhiều nhất:
Đây là các thuộc tính thống kê hiện tại của các phân vùng được sử dụng nhiều nhất:
Vấn đề
Tôi chạy một truy vấn đơn giản trên một tần số cao so với bảng.
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)
Kế hoạch thực hiện trông như thế này: https://www.brentozar.com/pastetheplan/?id=rJvI_4TtG
Vấn đề của tôi là các truy vấn này tạo ra số lượng hoạt động I / O cực kỳ cao dẫn đến tắc nghẽn PAGEIOLATCH_SH
chờ đợi.
Câu hỏi
Tôi đã đọc rằng PAGEIOLATCH_SH
chờ đợi thường liên quan đến các chỉ mục không được tối ưu hóa tốt. Bạn có đề xuất gì cho tôi về cách giảm hoạt động I / O không? Có lẽ bằng cách thêm một chỉ số tốt hơn?
Câu trả lời 1 - liên quan đến nhận xét từ @ S4V1N
Kế hoạch truy vấn được đăng là từ một truy vấn tôi đã thực hiện trong SSMS. Sau khi nhận xét của bạn, tôi làm một số nghiên cứu về lịch sử máy chủ. Truy vấn tình cờ xuất phát từ dịch vụ có vẻ hơi khác (liên quan đến 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)
Ngoài ra, kế hoạch có vẻ khác nhau:
https://www.brentozar.com/pastetheplan/?id=H1fhALpKG
hoặc là
https://www.brentozar.com/pastetheplan/?id=S1DFQvpKz
Và như bạn có thể thấy ở đây, hiệu suất DB của chúng tôi hầu như không bị ảnh hưởng bởi truy vấn này.
Câu trả lời 2 - liên quan đến câu trả lời từ @Joe Obbish
Để thử nghiệm giải pháp, tôi đã thay thế Entity Framework bằng một SqlCommand đơn giản. Kết quả là một hiệu suất tuyệt vời tăng!
Kế hoạch truy vấn bây giờ giống như trong SSMS và số lần đọc và ghi logic giảm xuống ~ 8 mỗi lần thực hiện.
Tổng tải I / O giảm xuống gần 0!
Nó cũng giải thích lý do tại sao tôi giảm hiệu suất lớn sau khi tôi thay đổi phạm vi phân vùng từ hàng tháng sang hàng ngày. Việc thiếu loại bỏ phân vùng dẫn đến nhiều phân vùng để quét.