ROW_NUMBER () OVER (พาร์ทิชันโดย B, A ORDER BY C) ไม่ได้ใช้ดัชนีใน (A, B, C)


12

พิจารณาทั้งสองฟังก์ชั่น:

ROW_NUMBER() OVER (PARTITION BY A,B ORDER BY C)

ROW_NUMBER() OVER (PARTITION BY B,A ORDER BY C)

เท่าที่ฉันเข้าใจพวกเขาให้ผลลัพธ์ที่เหมือนกันทุกประการ ในคำอื่น ๆ ลำดับที่คุณแสดงรายการคอลัมน์ในPARTITION BYข้อไม่สำคัญ

หากมีดัชนีอยู่(A,B,C)ฉันคาดว่าเครื่องมือเพิ่มประสิทธิภาพจะใช้ดัชนีนี้ในทั้งสองรุ่น

แต่น่าประหลาดใจที่ผู้เพิ่มประสิทธิภาพตัดสินใจทำการจัดเรียงที่ชัดเจนเป็นพิเศษในชุดที่สอง

ฉันเคยเห็นมันใน SQL Server 2008 Standard และ SQL Server 2014 Express

นี่เป็นสคริปต์เต็มรูปแบบที่ฉันใช้ในการทำซ้ำ

พยายามใน Microsoft SQL Server 2014 - 12.0.2000.8 (X64) 20 กุมภาพันธ์ 2014 20:04:26 ลิขสิทธิ์ (c) Microsoft Corporation Express Edition (64 บิต) บน Windows NT 6.1 (รุ่น 7601: Service Pack 1)

และ Microsoft SQL Server 2014 (SP1-CU7) (KB3162659) - 12.0.4459.0 (X64) 27 พฤษภาคม 2559 15:33:17 ลิขสิทธิ์ (c) Microsoft Corporation Express Edition (64 บิต) บน Windows NT 6.1 (รุ่น 7601: Service แพ็ค 1)

ที่มีทั้งเก่าและใหม่ Cardinality ประมาณการโดยใช้และOPTION (QUERYTRACEON 9481)OPTION (QUERYTRACEON 2312)

ตั้งค่าตารางดัชนีข้อมูลตัวอย่าง

CREATE TABLE [dbo].[T](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [A] [int] NOT NULL,
    [B] [int] NOT NULL,
    [C] [int] NOT NULL,
    CONSTRAINT [PK_T] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, 
STATISTICS_NORECOMPUTE = OFF, 
IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, 
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE NONCLUSTERED INDEX [IX_ABC] ON [dbo].[T]
(
    [A] ASC,
    [B] ASC,
    [C] ASC
)WITH (PAD_INDEX = OFF, 
STATISTICS_NORECOMPUTE = OFF, 
SORT_IN_TEMPDB = OFF, 
DROP_EXISTING = OFF, 
ONLINE = OFF, 
ALLOW_ROW_LOCKS = ON, 
ALLOW_PAGE_LOCKS = ON)
GO

INSERT INTO [dbo].[T] ([A],[B],[C]) VALUES
(10, 20, 30),
(10, 21, 31),
(10, 21, 32),
(10, 21, 33),
(11, 20, 34),
(11, 21, 35),
(11, 21, 36),
(12, 20, 37),
(12, 21, 38),
(13, 21, 39);

แบบสอบถาม

SELECT -- AB
    ID,A,B,C
    ,ROW_NUMBER() OVER (PARTITION BY A,B ORDER BY C) AS rnAB
FROM T
ORDER BY C
OPTION(RECOMPILE);

SELECT -- BA
    ID,A,B,C
    ,ROW_NUMBER() OVER (PARTITION BY B,A ORDER BY C) AS rnBA
FROM T
ORDER BY C
OPTION(RECOMPILE);

SELECT -- both
    ID,A,B,C
    ,ROW_NUMBER() OVER (PARTITION BY A,B ORDER BY C) AS rnAB
    ,ROW_NUMBER() OVER (PARTITION BY B,A ORDER BY C) AS rnBA
FROM T
ORDER BY C
OPTION(RECOMPILE);

แผนการดำเนินการ

พาร์ทิชันโดย A, B

AB

พาร์ทิชันโดย B, A

บริติชแอร์เวย์

ทั้งสอง

ทั้งสอง

อย่างที่คุณเห็นแผนสองมีการเรียงพิเศษ มันสั่งโดย B, A, C ดูเหมือนว่าเครื่องมือเพิ่มประสิทธิภาพนั้นไม่ฉลาดพอที่จะตระหนักได้ว่าPARTITION BY B,AเหมือนกันPARTITION BY A,Bและเรียงลำดับข้อมูลใหม่

ที่น่าสนใจแบบสอบถามที่สามมีทั้งสองแบบROW_NUMBERและไม่มีการเรียงลำดับพิเศษ! แผนเหมือนกันกับแบบสอบถามแรก (โครงการลำดับมีการแสดงออกพิเศษในรายการเอาท์พุทสำหรับคอลัมน์พิเศษ แต่ไม่มีการเรียงลำดับพิเศษ) ดังนั้นในกรณีนี้มีความซับซ้อนมากขึ้นเพิ่มประสิทธิภาพดูเหมือนจะฉลาดพอที่จะรู้ว่าเป็นเช่นเดียวกับPARTITION BY B,APARTITION BY A,B

ในการสืบค้นแรกและครั้งที่สามผู้ดำเนินการสแกนดัชนีมีคุณสมบัติสั่งซื้อ: จริงในการสืบค้นที่สองเป็นการเท็จ

น่าสนใจยิ่งขึ้นถ้าฉันเขียนข้อความค้นหาที่สามแบบนี้อีกครั้ง (สลับสองคอลัมน์):

SELECT -- both
    ID,A,B,C
    ,ROW_NUMBER() OVER (PARTITION BY B,A ORDER BY C) AS rnBA
    ,ROW_NUMBER() OVER (PARTITION BY A,B ORDER BY C) AS rnAB
FROM T
ORDER BY C
OPTION(RECOMPILE);

จากนั้นเรียงพิเศษจะปรากฏขึ้นอีกครั้ง!

มีใครบ้างที่สามารถส่องแสงบ้างไหม? เกิดอะไรขึ้นในเครื่องมือเพิ่มประสิทธิภาพที่นี่


ความคิดเห็นที่เก็บไว้
พอลไวท์ 9

คำตอบ:


2

ดูเหมือนว่าไม่มี "คำตอบ" ที่ชัดเจนสำหรับคำถาม "สิ่งที่เกิดขึ้นในเครื่องมือเพิ่มประสิทธิภาพ" เว้นแต่คุณจะเป็นนักพัฒนาซอฟต์แวร์และรู้จักภายใน

ฉันจะรวบรวมความคิดเห็นที่นี่

โดยรวมแล้วดูเหมือนว่าจะรุนแรงเกินไปที่จะเรียกว่าข้อบกพร่องเนื่องจากผลลัพธ์สุดท้ายของแบบสอบถามนั้นถูกต้อง ในบางกรณีแผนการดำเนินการอาจไม่เหมาะสมที่สุด ypercubeᵀᴹ , Martin SmithและAaron Bertrandเรียกมันว่า "การเพิ่มประสิทธิภาพที่ไม่ได้รับ"

  • ดูเหมือนGROUP BY a,bและGROUP BY b,aให้ผลเหมือนกัน แต่PARTITION BYไม่สามารถใช้การแปลงแบบเดียวกันได้

  • มีการเพิ่มประสิทธิภาพที่ขาดหายไปอื่น ๆ เช่นกันที่ฟังก์ชั่นหน้าต่างที่มีคุณสมบัติของหน้าต่างเดียวกันสามารถมีการดำเนินการเรียงลำดับพิเศษหากแยกในรายการที่เลือกโดยหนึ่งด้วยสเปคที่แตกต่างกัน

  • ใช่ดูเหมือนว่าจะมีการเพิ่มประสิทธิภาพที่ไม่ได้รับอีกและมีมากมาย เครื่องมือเพิ่มประสิทธิภาพนั้นเขียนขึ้นโดยมนุษย์และไม่สมบูรณ์แบบ


มีบทความที่เกี่ยวข้องบ้างเล็กน้อยจากมากไปน้อยดัชนี การจัดลำดับดัชนีการขนานและการคำนวณการจัดอันดับโดย Itzik Ben-Gan มี Itzik กล่าวถึงดัชนีจากมากไปน้อยและยังให้ตัวอย่างว่าทิศทางของคำนิยามดัชนีมีผลต่อฟังก์ชั่นหน้าต่างที่มีพาร์ทิชัน เขาแสดงตัวอย่างของคิวรีและแผนที่สร้างขึ้นโดยROW_NUMBERมีตัวดำเนินการเรียงลำดับพิเศษที่เครื่องมือเพิ่มประสิทธิภาพสามารถหลีกเลี่ยงได้


สำหรับฉันแล้วผลลัพธ์ที่ใช้ได้คือการรักษาความมีเอกลักษณ์ของผู้เพิ่มประสิทธิภาพไว้ในใจ เมื่อใช้PARTITION BYในฟังก์ชั่นหน้าต่างพยายามที่จะจับคู่กับลำดับที่คุณแสดงรายการคอลัมน์PARTITION BYตามลำดับที่พวกเขาอยู่ในดัชนี แม้ว่ามันจะไม่สำคัญก็ตาม

อีกด้านของข้อควรระวังนี้คือเมื่อคุณตรวจสอบดัชนีของคุณและตัดสินใจที่จะสลับบางคอลัมน์ในนิยามดัชนี โปรดทราบว่าคุณอาจส่งผลต่อข้อความค้นหาที่มีอยู่ซึ่งไม่ควรได้รับผลกระทบโดยไม่ตั้งใจ นี่คือวิธีที่ฉันสังเกตเห็นความผิดปกติของเครื่องมือเพิ่มประสิทธิภาพนี้

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

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