订购分区表的最佳方式是什么?

gro*_*chu -2 order-by partitioning sql-server-2016

从分区表中获取有序数据的最有效方法是什么?

我有这样的疑问:

SELECT TOP (4000)
*
FROM dbo.MS
ORDER BY MANDT
, MBLNR
, MJAHR
, ZEILE
Run Code Online (Sandbox Code Playgroud)

表按 MBLNR 分区。

执行计划:https://www.brentozar.com/pastetheplan/? id=Bkhv5g5EF

是否有任何选项可以从执行计划中删除排序?

建表语句:

CREATE TABLE [dbo].[MS]
(
    [MANDT] [NVARCHAR](3) NOT NULL
    , [MBLNR] [NVARCHAR](10) NOT NULL
    , [MJAHR] [NVARCHAR](4) NOT NULL
    , [ZEILE] [NVARCHAR](4) NOT NULL
    , [LINE_ID] [NVARCHAR](6) NOT NULL
    , [PARENT_ID] [NVARCHAR](6) NOT NULL
    , [LINE_DEPTH] [NVARCHAR](2) NOT NULL
    , [MAA_URZEI] [NVARCHAR](4) NOT NULL
    , [BWART] [NVARCHAR](3) NOT NULL
    , [XAUTO] [NVARCHAR](1) NOT NULL
    , [MATNR] [NVARCHAR](18) NOT NULL
    , [WERKS] [NVARCHAR](4) NOT NULL
    , [LGORT] [NVARCHAR](4) NOT NULL
    , [CHARG] [NVARCHAR](10) NOT NULL
    , [INSMK] [NVARCHAR](1) NOT NULL
    , [ZUSCH] [NVARCHAR](1) NOT NULL
    , [ZUSTD] [NVARCHAR](1) NOT NULL
    , [SOBKZ] [NVARCHAR](1) NOT NULL
    , [LIFNR] [NVARCHAR](10) NOT NULL
    , [KUNNR] [NVARCHAR](10) NOT NULL
    , [KDAUF] [NVARCHAR](10) NOT NULL
    , [KDPOS] [NVARCHAR](6) NOT NULL
    , [KDEIN] [NVARCHAR](4) NOT NULL
    , [PLPLA] [NVARCHAR](10) NOT NULL
    , [SHKZG] [NVARCHAR](1) NOT NULL
    , [WAERS] [NVARCHAR](5) NOT NULL
    , [DMBTR] [DECIMAL](13, 2) NOT NULL
    , [BNBTR] [DECIMAL](13, 2) NOT NULL
    , [BUALT] [DECIMAL](13, 2) NOT NULL
    , [SHKUM] [NVARCHAR](1) NOT NULL
    , [DMBUM] [DECIMAL](13, 2) NOT NULL
    , [BWTAR] [NVARCHAR](10) NOT NULL
    , [MENGE] [DECIMAL](13, 3) NOT NULL
    , [MEINS] [NVARCHAR](3) NOT NULL
    , [ERFMG] [DECIMAL](13, 3) NOT NULL
    , [ERFME] [NVARCHAR](3) NOT NULL
    , [BPMNG] [DECIMAL](13, 3) NOT NULL
    , [BPRME] [NVARCHAR](3) NOT NULL
    , [EBELN] [NVARCHAR](10) NOT NULL
    , [EBELP] [NVARCHAR](5) NOT NULL
    , [LFBJA] [NVARCHAR](4) NOT NULL
    , [LFBNR] [NVARCHAR](10) NOT NULL
    , [LFPOS] [NVARCHAR](4) NOT NULL
    , [SJAHR] [NVARCHAR](4) NOT NULL
    , [SMBLN] [NVARCHAR](10) NOT NULL
    , [SMBLP] [NVARCHAR](4) NOT NULL
    , [ELIKZ] [NVARCHAR](1) NOT NULL
    , [SGTXT] [NVARCHAR](50) NOT NULL
    , [EQUNR] [NVARCHAR](18) NOT NULL
    , [WEMPF] [NVARCHAR](12) NOT NULL
    , [ABLAD] [NVARCHAR](25) NOT NULL
    , [GSBER] [NVARCHAR](4) NOT NULL
    , [KOKRS] [NVARCHAR](4) NOT NULL
    , [PARGB] [NVARCHAR](4) NOT NULL
    , [PARBU] [NVARCHAR](4) NOT NULL
    , [KOSTL] [NVARCHAR](10) NOT NULL
    , [PROJN] [NVARCHAR](16) NOT NULL
    , [AUFNR] [NVARCHAR](12) NOT NULL
    , [ANLN1] [NVARCHAR](12) NOT NULL
    , [ANLN2] [NVARCHAR](4) NOT NULL
    , [XSKST] [NVARCHAR](1) NOT NULL
    , [XSAUF] [NVARCHAR](1) NOT NULL
    , [XSPRO] [NVARCHAR](1) NOT NULL
    , [XSERG] [NVARCHAR](1) NOT NULL
    , [GJAHR] [NVARCHAR](4) NOT NULL
    , [XRUEM] [NVARCHAR](1) NOT NULL
    , [XRUEJ] [NVARCHAR](1) NOT NULL
    , [BUKRS] [NVARCHAR](4) NOT NULL
    , [BELNR] [NVARCHAR](10) NOT NULL
    , [BUZEI] [NVARCHAR](3) NOT NULL
    , [BELUM] [NVARCHAR](10) NOT NULL
    , [BUZUM] [NVARCHAR](3) NOT NULL
    , [RSNUM] [NVARCHAR](10) NOT NULL
    , [RSPOS] [NVARCHAR](4) NOT NULL
    , [KZEAR] [NVARCHAR](1) NOT NULL
    , [PBAMG] [DECIMAL](13, 3) NOT NULL
    , [KZSTR] [NVARCHAR](1) NOT NULL
    , [UMMAT] [NVARCHAR](18) NOT NULL
    , [UMWRK] [NVARCHAR](4) NOT NULL
    , [UMLGO] [NVARCHAR](4) NOT NULL
    , [UMCHA] [NVARCHAR](10) NOT NULL
    , [UMZST] [NVARCHAR](1) NOT NULL
    , [UMZUS] [NVARCHAR](1) NOT NULL
    , [UMBAR] [NVARCHAR](10) NOT NULL
    , [UMSOK] [NVARCHAR](1) NOT NULL
    , [KZBEW] [NVARCHAR](1) NOT NULL
    , [KZVBR] [NVARCHAR](1) NOT NULL
    , [KZZUG] [NVARCHAR](1) NOT NULL
    , [WEUNB] [NVARCHAR](1) NOT NULL
    , [PALAN] [DECIMAL](11, 0) NOT NULL
    , [LGNUM] [NVARCHAR](3) NOT NULL
    , [LGTYP] [NVARCHAR](3) NOT NULL
    , [LGPLA] [NVARCHAR](10) NOT NULL
    , [BESTQ] [NVARCHAR](1) NOT NULL
    , [BWLVS] [NVARCHAR](3) NOT NULL
    , [TBNUM] [NVARCHAR](10) NOT NULL
    , [TBPOS] [NVARCHAR](4) NOT NULL
    , [XBLVS] [NVARCHAR](1) NOT NULL
    , [VSCHN] [NVARCHAR](1) NOT NULL
    , [NSCHN] [NVARCHAR](1) NOT NULL
    , [DYPLA] [NVARCHAR](1) NOT NULL
    , [UBNUM] [NVARCHAR](10) NOT NULL
    , [TBPRI] [NVARCHAR](1) NOT NULL
    , [TANUM] [NVARCHAR](10) NOT NULL
    , [WEANZ] [NVARCHAR](3) NOT NULL
    , [GRUND] [NVARCHAR](4) NOT NULL
    , [EVERS] [NVARCHAR](2) NOT NULL
    , [EVERE] [NVARCHAR](2) NOT NULL
    , [IMKEY] [NVARCHAR](8) NOT NULL
    , [KSTRG] [NVARCHAR](12) NOT NULL
    , [PAOBJNR] [NVARCHAR](10) NOT NULL
    , [PRCTR] [NVARCHAR](10) NOT NULL
    , [PS_PSP_PNR] [NVARCHAR](8) NOT NULL
    , [NPLNR] [NVARCHAR](12) NOT NULL
    , [AUFPL] [NVARCHAR](10) NOT NULL
    , [APLZL] [NVARCHAR](8) NOT NULL
    , [AUFPS] [NVARCHAR](4) NOT NULL
    , [VPTNR] [NVARCHAR](10) NOT NULL
    , [FIPOS] [NVARCHAR](14) NOT NULL
    , [SAKTO] [NVARCHAR](10) NOT NULL
    , [BSTMG] [DECIMAL](13, 3) NOT NULL
    , [BSTME] [NVARCHAR](3) NOT NULL
    , [XWSBR] [NVARCHAR](1) NOT NULL
    , [EMLIF] [NVARCHAR](10) NOT NULL
    , [EXBWR] [DECIMAL](13, 2) NOT NULL
    , [VKWRT] [DECIMAL](13, 2) NOT NULL
    , [AKTNR] [NVARCHAR](10) NOT NULL
    , [ZEKKN] [NVARCHAR](2) NOT NULL
    , [VFDAT] [NVARCHAR](8) NOT NULL
    , [CUOBJ_CH] [NVARCHAR](18) NOT NULL
    , [EXVKW] [DECIMAL](13, 2) NOT NULL
    , [PPRCTR] [NVARCHAR](10) NOT NULL
    , [RSART] [NVARCHAR](1) NOT NULL
    , [GEBER] [NVARCHAR](10) NOT NULL
    , [FISTL] [NVARCHAR](16) NOT NULL
    , [MATBF] [NVARCHAR](18) NOT NULL
    , [UMMAB] [NVARCHAR](18) NOT NULL
    , [BUSTM] [NVARCHAR](4) NOT NULL
    , [BUSTW] [NVARCHAR](4) NOT NULL
    , [MENGU] [NVARCHAR](1) NOT NULL
    , [WERTU] [NVARCHAR](1) NOT NULL
    , [LBKUM] [DECIMAL](13, 3) NOT NULL
    , [SALK3] [DECIMAL](13, 2) NOT NULL
    , [VPRSV] [NVARCHAR](1) NOT NULL
    , [FKBER] [NVARCHAR](16) NOT NULL
    , [DABRBZ] [NVARCHAR](8) NOT NULL
    , [VKWRA] [DECIMAL](13, 2) NOT NULL
    , [DABRZ] [NVARCHAR](8) NOT NULL
    , [XBEAU] [NVARCHAR](1) NOT NULL
    , [LSMNG] [DECIMAL](13, 3) NOT NULL
    , [LSMEH] [NVARCHAR](3) NOT NULL
    , [KZBWS] [NVARCHAR](1) NOT NULL
    , [QINSPST] [NVARCHAR](1) NOT NULL
    , [URZEI] [NVARCHAR](4) NOT NULL
    , [J_1BEXBASE] [DECIMAL](13, 2) NOT NULL
    , [MWSKZ] [NVARCHAR](2) NOT NULL
    , [TXJCD] [NVARCHAR](15) NOT NULL
    , [EMATN] [NVARCHAR](18) NOT NULL
    , [J_1AGIRUPD] [NVARCHAR](1) NOT NULL
    , [VKMWS] [NVARCHAR](2) NOT NULL
    , [HSDAT] [NVARCHAR](8) NOT NULL
    , [BERKZ] [NVARCHAR](1) NOT NULL
    , [MAT_KDAUF] [NVARCHAR](10) NOT NULL
    , [MAT_KDPOS] [NVARCHAR](6) NOT NULL
    , [MAT_PSPNR] [NVARCHAR](8) NOT NULL
    , [XWOFF] [NVARCHAR](1) NOT NULL
    , [BEMOT] [NVARCHAR](2) NOT NULL
    , [PRZNR] [NVARCHAR](12) NOT NULL
    , [LLIEF] [NVARCHAR](10) NOT NULL
    , [LSTAR] [NVARCHAR](6) NOT NULL
    , [XOBEW] [NVARCHAR](1) NOT NULL
    , [GRANT_NBR] [NVARCHAR](20) NOT NULL
    , [ZUSTD_T156M] [NVARCHAR](1) NOT NULL
    , [SPE_GTS_STOCK_TY] [NVARCHAR](1) NOT NULL
    , [KBLNR] [NVARCHAR](10) NOT NULL
    , [KBLPOS] [NVARCHAR](3) NOT NULL
    , [XMACC] [NVARCHAR](1) NOT NULL
    , [VGART_MKPF] [NVARCHAR](2) NOT NULL
    , [BUDAT_MKPF] [NVARCHAR](8) NOT NULL
    , [CPUDT_MKPF] [NVARCHAR](8) NOT NULL
    , [CPUTM_MKPF] [NVARCHAR](6) NOT NULL
    , [USNAM_MKPF] [NVARCHAR](12) NOT NULL
    , [XBLNR_MKPF] [NVARCHAR](16) NOT NULL
    , [TCODE2_MKPF] [NVARCHAR](20) NOT NULL
    , [VBELN_IM] [NVARCHAR](10) NOT NULL
    , [VBELP_IM] [NVARCHAR](6) NOT NULL
    , [SGT_SCAT] [NVARCHAR](16) NOT NULL
    , [SGT_UMSCAT] [NVARCHAR](16) NOT NULL
    , [SGT_RCAT] [NVARCHAR](16) NOT NULL
    , [/BEV2/ED_KZ_VER] [NVARCHAR](1) NOT NULL
    , [/BEV2/ED_USER] [NVARCHAR](12) NOT NULL
    , [/BEV2/ED_AEDAT] [NVARCHAR](8) NOT NULL
    , [/BEV2/ED_AETIM] [NVARCHAR](6) NOT NULL
    , [DISUB_OWNER] [NVARCHAR](10) NOT NULL
    , [OINAVNW] [DECIMAL](13, 2) NOT NULL
    , [OICONDCOD] [NVARCHAR](2) NOT NULL
    , [CONDI] [NVARCHAR](2) NOT NULL
    , [WRF_CHARSTC1] [NVARCHAR](18) NOT NULL
    , [WRF_CHARSTC2] [NVARCHAR](18) NOT NULL
    , [WRF_CHARSTC3] [NVARCHAR](18) NOT NULL
    , [/BEV2/ED_AEDAT_SIMP_DT] AS (TRY_CONVERT([DATE], [/BEV2/ED_AEDAT], (112)))
    , [BUDAT_MKPF_SIMP_DT] AS (TRY_CONVERT([DATE], [BUDAT_MKPF], (112)))
    , [CPUDT_MKPF_SIMP_DT] AS (TRY_CONVERT([DATE], [CPUDT_MKPF], (112)))
    , [DABRBZ_SIMP_DT] AS (TRY_CONVERT([DATE], [DABRBZ], (112)))
    , [DABRZ_SIMP_DT] AS (TRY_CONVERT([DATE], [DABRZ], (112)))
    , [HSDAT_SIMP_DT] AS (TRY_CONVERT([DATE], [HSDAT], (112)))
    , [VFDAT_SIMP_DT] AS (TRY_CONVERT([DATE], [VFDAT], (112)))
    , [/BEV2/ED_AETIM_SIMP_TM] AS (TRY_CONVERT([TIME](0), CASE [/BEV2/ED_AETIM]
                                                          WHEN N'240000' THEN
                                                              N'23:59:59'
                                                          ELSE
                                                              STUFF(STUFF([/BEV2/ED_AETIM], (3), (0), N':'), (6), (0), N':')
                                                          END, (112))
                                  )
    , [CPUTM_MKPF_SIMP_TM] AS (TRY_CONVERT([TIME](0), CASE [CPUTM_MKPF]
                                                      WHEN N'240000' THEN
                                                          N'23:59:59'
                                                      ELSE
                                                          STUFF(STUFF([CPUTM_MKPF], (3), (0), N':'), (6), (0), N':')
                                                      END, (112))
                              )
    , CONSTRAINT [dbo_MS~0]
          PRIMARY KEY CLUSTERED
          (
              [MANDT] ASC
              , [MBLNR] ASC
              , [MJAHR] ASC
              , [ZEILE] ASC
          )
);
Run Code Online (Sandbox Code Playgroud)

分区函数:

CREATE PARTITION FUNCTION [PF_dbo_MS_SIMP] (NVARCHAR(10))
AS RANGE RIGHT FOR VALUES (
N'426811'
, N'426862'
, N'426916'
, N'426968'
, N'427022'
, N'427072'
, N'427124'
, N'427182'
, N'427238'
, N'427293'
, N'427349'
, N'427404'
, N'427459'
, N'427513'
, N'427569'
, N'427625'
, N'427680'
, N'427733'
, N'427784'
, N'427840'
, N'427893'
, N'427948'
, N'428002'
, N'428053'
, N'428105'
, N'428162'
, N'428216'
, N'428272'
, N'428328'
, N'428384'
, N'428437'
, N'428489'
, N'428547'
, N'428601'
, N'428659'
, N'428715'
, N'428769'
, N'428822'
, N'428878'
, N'428932'
, N'428986'
, N'429041'
, N'429089'
, N'429146'
, N'429204'
, N'429260'
, N'429313'
, N'429366'
, N'429418'
, N'429472'
, N'429528'
, N'429583'
, N'429638'
, N'429691'
, N'429745'
, N'429799'
, N'429856'
, N'429909'
, N'429961'
, N'430012'
, N'430063'
, N'430118'
, N'430171'
, N'430224'
, N'430276'
, N'430326'
, N'430381'
, N'430434'
, N'430489'
, N'430539'
, N'430591'
, N'430644'
, N'430698'
, N'430753'
, N'430805'
, N'430856'
, N'430906'
, N'430961'
, N'516464'
, N'516561'
, N'516664'
, N'516766'
, N'516868'
, N'516970'
, N'517071'
, N'517173'
, N'517274'
, N'517376'
, N'517478'
, N'517578'
, N'517678'
, N'517778'
, N'517879'
, N'517913'
);
Run Code Online (Sandbox Code Playgroud)

Pau*_*ite 7

分区将分区号作为隐含的主键添加到分区索引中。

您的聚集索引位于:

[MANDT] ASC, [MBLNR] ASC, [MJAHR] ASC, [ZEILE] ASC
Run Code Online (Sandbox Code Playgroud)

变成:

[<partition_id>], [MANDT] ASC, [MBLNR] ASC, [MJAHR] ASC, [ZEILE] ASC
Run Code Online (Sandbox Code Playgroud)

该指数无法提供以下所需的订单:

SELECT TOP (4000) *
FROM dbo.MS
ORDER BY MANDT, MBLNR, MJAHR, ZEILE
Run Code Online (Sandbox Code Playgroud)

每个分区中的行仅按照您想要的方式排序。

例如,这将返回分区 #1 中的行而不进行排序:

SELECT TOP (4000) *
FROM dbo.MS
WHERE $PARTITION.PF_dbo_MS_SIMP (MBLNR) = 1
ORDER BY MANDT, MBLNR, MJAHR, ZEILE
Run Code Online (Sandbox Code Playgroud)

您当前的聚集索引确实支持此顺序:

SELECT TOP (4000) * 
FROM dbo.MS
ORDER BY 
    $PARTITION.PF_dbo_MS_SIMP (MBLNR),  -- Partition ID
    MANDT, MBLNR, MJAHR, ZEILE;
Run Code Online (Sandbox Code Playgroud)

对此没有任何完美的解决方法。

  1. 您可以更改分区安排以适应此查询。这将是一个巨大而勇敢的改变。您需要根据您的工作负载和数据加载/归档安排来测试新方案。

  2. 您可以创建一个非分区二级索引,并希望优化器为您的查询选择一个书签查找计划,但是您的索引与基表不对齐。

    例如:

    CREATE UNIQUE NONCLUSTERED INDEX name_me 
    ON dbo.MS (MANDT, MBLNR, MJAHR, ZEILE) 
    ON [PRIMARY];
    
    Run Code Online (Sandbox Code Playgroud)
  3. 您可以生成一个像上面所示的每分区查询(包括顶部 (4000)),将它们全部合并在一起,然后从每分区合并的结果中选择顶部 (4000)。这需要一些动态 SQL(假设您的分区可能会随着时间的推移而改变)。

下面显示了仅三个分区的选项 2 的静态代码:

SELECT TOP (4000) * FROM
(
    SELECT * FROM 
    (
        SELECT TOP (4000) *
        FROM dbo.MS
        WHERE $PARTITION.PF_dbo_MS_SIMP (MBLNR) = 1
        ORDER BY MANDT, MBLNR, MJAHR, ZEILE
    ) AS P1
    UNION ALL
    SELECT * FROM 
    (
        SELECT TOP (4000) *
        FROM dbo.MS
        WHERE $PARTITION.PF_dbo_MS_SIMP (MBLNR) = 2
        ORDER BY MANDT, MBLNR, MJAHR, ZEILE
    ) AS P2
    UNION ALL
    SELECT * FROM 
    (
        SELECT TOP (4000) *
        FROM dbo.MS
        WHERE $PARTITION.PF_dbo_MS_SIMP (MBLNR) = 3
        ORDER BY MANDT, MBLNR, MJAHR, ZEILE
    ) AS P3
) AS M
ORDER BY MANDT, MBLNR, MJAHR, ZEILE;
Run Code Online (Sandbox Code Playgroud)

执行计划是:

合并工会计划

每个“扫描”都是对单个分区的扫描(该扫描具有查找谓词)。注意缺乏排序。

该计划是非阻塞的,并且合并串联是保序的。这意味着总共最多会读取 4000 行。该计划不会每个分区读取最多 4000 行。