เหตุใดจึงไม่ใช้คีย์หลัก (คลัสเตอร์) ในการสืบค้นนี้


10

ฉันมีตาราง SQL Server 2008 R2 ซึ่งโครงสร้างสกีมามีลักษณะดังนี้:

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

และฉันกำลังดำเนินการค้นหาง่าย ๆ นี้:

Select Max(Id)
From dbo.CDSIM_BE

มีแถว ~ 2.5B ในตาราง

แผนแบบสอบถามจะแสดงการสแกนดัชนีที่ทำในIX_CdSIM_BE_ProbePositionดัชนี ฉันสงสัยว่าทำไม SQL Server จะไม่ใช้ดัชนีคลัสเตอร์ (และหลัก) และไปที่แถวสุดท้ายในตารางทันทีและดึงค่า Id เนื่องจากจะต้องมีค่าสูงสุด


max ()และนาที ()มวลรวมมักจะมีปัญหาในการนี้ หากคุณต้องการให้แน่ใจว่ามีการใช้ดัชนีเขียนแทนselect top 1 Id from dbo.CDSIM_BE order by Id descending;
Pieter Geerkens

4
ดัชนีคลัสเตอร์ถูกแบ่งพาร์ติชันReadTimeเพื่อไม่สามารถใช้ PK ได้ตามที่คุณอธิบาย มันจะต้องไปหาMax(Id)สำหรับแต่ละพาร์ทิชันแล้วพบสูงสุดของคนเหล่านั้น เป็นไปได้ที่จะเขียนข้อความค้นหาใหม่เพื่อรับแผนดังกล่าวที่กล่าวถึงในที่นี้แม้ว่าdba.stackexchange.com/a/99418/3690
Martin Smith

คำตอบ:


7

ดัชนีคลัสเตอร์ถูกแบ่งพาร์ติชันReadTimeเพื่อไม่สามารถใช้ PK ได้ตามที่คุณอธิบาย มันจะต้องค้นหาMax(Id)สำหรับแต่ละพาร์ติชันแล้วหาค่าสูงสุด มันเป็นไปได้ที่จะเขียนแบบสอบถามเพื่อให้ได้แผนดังกล่าวอย่างไร

การใช้ตัวอย่างจากบทความที่นี่อาจมีการเขียนซ้ำ

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; 

ในการประมวลผลแต่ละพาร์ติชันในทางกลับกัน

หมายเหตุแผนยังคงมีการสแกน (พร้อมเพรดิเคตแสวงหาเพื่อเลือกพาร์ติชัน) แต่นี่ไม่ใช่การสแกนแบบเต็มของพาร์ติชัน

การสแกนอยู่ในลำดับดัชนีโดยมีทิศทาง "BACKWARD" ตัวTOPวนซ้ำสามารถหยุดการร้องขอแถวจากการสแกนหลังจากได้รับแถวแรก

ป้อนคำอธิบายรูปภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.