Tại sao khóa chính (cụm) không được sử dụng trong truy vấn này?


10

Tôi có một bảng SQL Server 2008 R2 có cấu trúc lược đồ như sau:

CREATE TABLE [dbo].[CDSIM_BE]
(
    [ID] [bigint] NOT NULL,
    [EquipmentID] [varchar](50) NOT NULL,
    [SerialNumber] [varchar](50) NULL,
    [PyrID] [varchar](50) NULL,
    [MeasMode] [varchar](50) NULL,
    [ReadTime] [datetime] NOT NULL,
    [SubID] [varchar](15) NULL,
    [ProbePosition] [float] NULL,
    [DataPoint] [int] NULL,

    CONSTRAINT [PK_CDSIM_BE] 
    PRIMARY KEY CLUSTERED ([ID] ASC, [EquipmentID] ASC, [ReadTime] ASC)
         WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
               IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
               ALLOW_PAGE_LOCKS = ON) ON [MonthlyArchiveScheme9]([ReadTime])
) ON [MonthlyArchiveScheme9]([ReadTime])

CREATE NONCLUSTERED INDEX [idx_CDSIM_BE__SubID_ProbePosition] 
ON [dbo].[CDSIM_BE] ([SubID] ASC, [ProbePosition] ASC)
INCLUDE ([EquipmentID], [ReadTime], [BECorr]) 
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
          SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, 
          ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [MonthlyArchiveScheme9]([ReadTime])

CREATE NONCLUSTERED INDEX [IX_CDSIM_BE_ProbePosition] 
ON [dbo].[CDSIM_BE] ([ProbePosition] ASC)
INCLUDE ([SerialNumber], [SubID]) 
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
          SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, 
          ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [MonthlyArchiveScheme9]([ReadTime])

CREATE NONCLUSTERED INDEX [IX_CSDIM_Readtime] 
ON [dbo].[CDSIM_BE]([ReadTime] ASC)
INCLUDE ([EquipmentID]) 
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
          SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, 
          ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [MonthlyArchiveScheme9]([ReadTime])

Và tôi đang thực hiện truy vấn đơn giản này:

Select Max(Id)
From dbo.CDSIM_BE

Có ~ 2,5B hàng trong bảng.

Kế hoạch truy vấn cho thấy quét chỉ mục đang được thực hiện trên IX_CdSIM_BE_ProbePositionchỉ mục. Tôi tự hỏi tại sao SQL Server đơn giản là không sử dụng chỉ mục được phân cụm (và chính) và ngay lập tức đi đến hàng cuối cùng trong bảng và truy xuất giá trị Id, vì đó phải là giá trị tối đa.


Các tổng hợp max ()min () thường có vấn đề về vấn đề này. Nếu bạn muốn chắc chắn một chỉ mục được sử dụng, hãy viết thay vào đóselect top 1 Id from dbo.CDSIM_BE order by Id descending;
Pieter Geerkens

4
Chỉ mục cụm được phân vùng trên ReadTimeđể nó không thể sử dụng PK như bạn mô tả. Nó sẽ cần phải tìm Max(Id)cho mỗi phân vùng và sau đó tìm tối đa của các phân vùng. Có thể viết lại truy vấn để có được một kế hoạch như được đề cập ở đây mặc dù dba.stackexchange.com/a/99418/3690
Martin Smith

Câu trả lời:


7

Chỉ mục cụm được phân vùng trên ReadTimeđể nó không thể sử dụng PK như bạn mô tả. Nó sẽ cần phải tìm Max(Id)cho mỗi phân vùng và sau đó tìm tối đa của các phân vùng. Nó có thể phải viết lại các truy vấn để có được một kế hoạch như vậy tuy nhiên.

Sử dụng một ví dụ dựa trên bài viết ở đây có thể viết lại

SELECT MAX(ID) AS ID
FROM   sys.partitions AS P
       CROSS APPLY (SELECT MAX(ID) AS ID
                    FROM   [dbo].[CDSIM_BE]
                    WHERE  $PARTITION.MonthlyArchiveFunction9(ReadTime) 
                                                    = P.partition_number) AS A
WHERE  P.object_id = OBJECT_ID('dbo.CDSIM_BE')
       AND P.index_id <= 1; 

Để xử lý lần lượt từng phân vùng.

Lưu ý rằng kế hoạch vẫn có quét (với một vị từ tìm kiếm để chọn phân vùng) nhưng đây không phải là quét toàn bộ phân vùng.

Quá trình quét theo thứ tự chỉ mục theo hướng "BACKWARD". Trình TOPlặp có thể dừng yêu cầu các hàng từ quá trình quét sau khi nhận được lần đầu tiên.

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.