Bu sorguda neden birincil (kümelenmiş) anahtar kullanılmıyor?


10

Şema yapısı aşağıdaki gibi görünüyor bir SQL Server 2008 R2 tablo var:

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

Ve ben bu basit sorguyu yürütüyorum:

Select Max(Id)
From dbo.CDSIM_BE

Tabloda ~ 2.5B satır var.

Sorgu planı, dizinde yapılan bir dizin taramasını gösterir IX_CdSIM_BE_ProbePosition. Neden SQL Server sadece kümelenmiş (ve birincil) dizini kullanmak ve hemen tablodaki son satıra gitmek ve Id değeri almak gerekir merak ediyorum, çünkü bu maksimum olmalıdır.


V max () ve dakika () agrega genellikle bu açısından sorunludur. Bunun yerine bir dizinin kullanıldığından emin olmak istiyorsanızselect top 1 Id from dbo.CDSIM_BE order by Id descending;
Pieter Geerkens

4
Kümelenmiş dizin bölümlere ayrılmıştır, ReadTimeböylece açıkladığınız gibi PK'yi kullanamaz. Bulmak gerekir Max(Id)her bölüm için ve daha sonra bunlardan max bulabilirsiniz. Burada belirtildiği gibi bir plan almak için sorguyu yeniden yazmak mümkündür, ancak dba.stackexchange.com/a/99418/3690
Martin Smith

Yanıtlar:


7

Kümelenmiş dizin bölümlere ayrılmıştır, ReadTimeböylece açıkladığınız gibi PK'yi kullanamaz. Bulmak gerekir Max(Id)her bölüm için ve daha sonra bunlardan max bulabilirsiniz. İse ancak bu tür bir plan almak için sorguyu yeniden yazmak mümkün.

Buradaki makaleye dayanan bir örnek kullanarak olası bir yeniden yazma

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; 

Her bölümü sırayla işlemek için.

Planın hala bir taraması olduğunu (bölümü seçmek için bir arama öngörüsü ile) unutmayın, ancak bu bölümün tam bir taraması değildir.

Tarama "GERİ" yönü ile dizin düzenindedir. TOPBirincisi alındıktan sonra yineleyici tarama satır talep durdurabilir.

resim açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.