พิจารณาทั้งสองฟังก์ชั่น:
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
พาร์ทิชันโดย B, A
ทั้งสอง
อย่างที่คุณเห็นแผนสองมีการเรียงพิเศษ มันสั่งโดย B, A, C ดูเหมือนว่าเครื่องมือเพิ่มประสิทธิภาพนั้นไม่ฉลาดพอที่จะตระหนักได้ว่าPARTITION BY B,A
เหมือนกันPARTITION BY A,B
และเรียงลำดับข้อมูลใหม่
ที่น่าสนใจแบบสอบถามที่สามมีทั้งสองแบบROW_NUMBER
และไม่มีการเรียงลำดับพิเศษ! แผนเหมือนกันกับแบบสอบถามแรก (โครงการลำดับมีการแสดงออกพิเศษในรายการเอาท์พุทสำหรับคอลัมน์พิเศษ แต่ไม่มีการเรียงลำดับพิเศษ) ดังนั้นในกรณีนี้มีความซับซ้อนมากขึ้นเพิ่มประสิทธิภาพดูเหมือนจะฉลาดพอที่จะรู้ว่าเป็นเช่นเดียวกับPARTITION BY B,A
PARTITION 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);
จากนั้นเรียงพิเศษจะปรากฏขึ้นอีกครั้ง!
มีใครบ้างที่สามารถส่องแสงบ้างไหม? เกิดอะไรขึ้นในเครื่องมือเพิ่มประสิทธิภาพที่นี่