Mengapa kunci primer (berkerumun) tidak digunakan dalam permintaan ini?


10

Saya memiliki tabel SQL Server 2008 R2 yang struktur skimnya terlihat sebagai berikut:

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])

Dan saya menjalankan permintaan sederhana ini:

Select Max(Id)
From dbo.CDSIM_BE

Ada ~ 2.5B baris dalam tabel.

Rencana kueri menunjukkan pemindaian indeks yang dilakukan pada IX_CdSIM_BE_ProbePositionindeks. Saya bertanya-tanya mengapa SQL Server tidak akan menggunakan indeks berkerumun (dan utama) dan segera pergi ke baris terakhir dalam tabel dan mengambil nilai Id, karena itu harus maksimum.


The max () dan min () agregat sering bermasalah dalam hal ini. Jika Anda ingin memastikan indeks digunakan, tulislahselect top 1 Id from dbo.CDSIM_BE order by Id descending;
Pieter Geerkens

4
Indeks berkerumun dipartisi ReadTimesehingga tidak dapat menggunakan PK seperti yang Anda gambarkan. Perlu menemukan Max(Id)untuk setiap partisi dan kemudian menemukan maksnya. Dimungkinkan untuk menulis ulang kueri untuk mendapatkan rencana seperti yang disinggung di sini melalui dba.stackexchange.com/a/99418/3690
Martin Smith

Jawaban:


7

Indeks berkerumun dipartisi ReadTimesehingga tidak dapat menggunakan PK seperti yang Anda gambarkan. Perlu menemukan Max(Id)untuk setiap partisi dan kemudian menemukan maksnya. Hal ini dimungkinkan untuk menulis ulang query untuk mendapatkan rencana tersebut namun.

Menggunakan contoh berdasarkan artikel di sini kemungkinan penulisan ulang

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; 

Untuk memproses setiap partisi secara bergantian.

Perhatikan bahwa paket tersebut masih memiliki pemindaian (dengan predikat pencarian untuk memilih partisi) tetapi ini bukan pemindaian penuh partisi.

Pemindaian dalam urutan indeks dengan arah "BACKWARD". The TOPiterator dapat menghentikan meminta baris dari scan setelah yang pertama diterima.

masukkan deskripsi gambar di sini

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.