สำหรับสคีมาและข้อมูลตัวอย่างต่อไปนี้
CREATE TABLE T
(
A INT NULL,
B INT NOT NULL IDENTITY,
C CHAR(8000) NULL,
UNIQUE CLUSTERED (A, B)
)
INSERT INTO T
(A)
SELECT NULLIF(( ( ROW_NUMBER() OVER (ORDER BY @@SPID) - 1 ) / 1003 ), 0)
FROM master..spt_values
แอปพลิเคชันกำลังประมวลผลแถวจากตารางนี้ในลำดับดัชนีแบบกลุ่มเป็นกลุ่ม 1,000 แถว
1,000 แถวแรกจะถูกดึงออกมาจากแบบสอบถามต่อไปนี้
SELECT TOP 1000 *
FROM T
ORDER BY A, B
แถวสุดท้ายของชุดนั้นอยู่ด้านล่าง
+------+------+
| A | B |
+------+------+
| NULL | 1000 |
+------+------+
มีวิธีใดในการเขียนคิวรีที่พยายามค้นหาคีย์ดัชนีคอมโพสิตนั้นจากนั้นติดตามมันเพื่อดึงข้อมูลอันถัดไปของแถว 1,000 แถว?
/*Pseudo Syntax*/
SELECT TOP 1000 *
FROM T
WHERE (A, B) is_ordered_after (@A, @B)
ORDER BY A, B
จำนวนการอ่านต่ำสุดที่ฉันได้รับจนถึงขณะนี้คือ 1,020 ข้อความค้นหาดูเหมือนซับซ้อนเกินไป มีวิธีที่ง่ายกว่าเท่ากันหรือมีประสิทธิภาพที่ดีขึ้น? บางทีคนที่จัดการเพื่อทำทุกอย่างในระยะเดียวแสวงหา?
DECLARE @A INT = NULL, @B INT = 1000
;WITH UnProcessed
AS (SELECT *
FROM T
WHERE ( EXISTS(SELECT A
INTERSECT
SELECT @A)
AND B > @B )
UNION ALL
SELECT *
FROM T
WHERE @A IS NULL AND A IS NOT NULL
UNION ALL
SELECT *
FROM T
WHERE A > @A
)
SELECT TOP 1000 *
FROM UnProcessed
ORDER BY A,
B
FWIW: ถ้าคอลัมน์A
ทำNOT NULL
และค่าแมวมองของ-1
ที่ใช้แทนแผนปฏิบัติการเทียบเท่าแน่นอนดูง่าย
แต่ตัวดำเนินการค้นหาเดี่ยวในแผนยังคงทำการค้นหาสองรายการแทนที่จะยุบลงในช่วงที่ต่อเนื่องเดี่ยวและการอ่านแบบลอจิคัลจะเหมือนกันมากดังนั้นฉันจึงสงสัยว่านี่อาจจะดีเท่าที่ควร
(NULL, 1000 )
@A
เป็นโมฆะหรือไม่ดูเหมือนว่าจะไม่ทำการสแกน แต่ฉันไม่เข้าใจว่าแผนดีกว่าแบบสอบถามของคุณหรือไม่ Fiddle-2
NULL
ค่านั้นมักจะเป็นอันดับแรกเสมอ (สันนิษฐานว่าตรงกันข้าม) แก้ไขเงื่อนไขที่Fiddle