이 쿼리에서 기본 (클러스터) 키가 사용되지 않는 이유는 무엇입니까?


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 값을 검색하는 이유가 궁금합니다.


최대 ()분 () 집계는 자주 안부 문제가있다. 당신이 원하는 경우 반드시 인덱스가 사용되는 쓰기 대신입니다select top 1 Id from dbo.CDSIM_BE order by Id descending;
피터 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.