ฉันได้อ่านบ่อยเมื่อมีการตรวจสอบการดำรงอยู่ของแถวควรเสมอทำได้ด้วย EXISTS แทนกับการนับ
แต่ในหลายสถานการณ์ที่ผ่านมาฉันได้วัดการปรับปรุงประสิทธิภาพเมื่อใช้การนับ
รูปแบบเป็นไปดังนี้:
LEFT JOIN (
SELECT
someID
, COUNT(*)
FROM someTable
GROUP BY someID
) AS Alias ON (
Alias.someID = mainTable.ID
)
ฉันไม่คุ้นเคยกับวิธีการที่จะบอกว่าเกิดอะไรขึ้น "ภายใน" SQL Server ดังนั้นฉันจึงสงสัยว่ามีข้อผิดพลาดที่ไม่มีผู้แปลที่มี EXISTS ที่ให้ความรู้สึกที่สมบูรณ์แบบกับการวัดที่ฉันทำ
คุณมีคำอธิบายเกี่ยวกับปรากฏการณ์นั้นบ้างไหม?
แก้ไข:
นี่คือสคริปต์เต็มรูปแบบที่คุณสามารถเรียกใช้:
SET NOCOUNT ON
SET STATISTICS IO OFF
DECLARE @tmp1 TABLE (
ID INT UNIQUE
)
DECLARE @tmp2 TABLE (
ID INT
, X INT IDENTITY
, UNIQUE (ID, X)
)
; WITH T(n) AS (
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master.dbo.spt_values AS S
)
, tally(n) AS (
SELECT
T2.n * 100 + T1.n
FROM T AS T1
CROSS JOIN T AS T2
WHERE T1.n <= 100
AND T2.n <= 100
)
INSERT @tmp1
SELECT n
FROM tally AS T1
WHERE n < 10000
; WITH T(n) AS (
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master.dbo.spt_values AS S
)
, tally(n) AS (
SELECT
T2.n * 100 + T1.n
FROM T AS T1
CROSS JOIN T AS T2
WHERE T1.n <= 100
AND T2.n <= 100
)
INSERT @tmp2
SELECT T1.n
FROM tally AS T1
CROSS JOIN T AS T2
WHERE T1.n < 10000
AND T1.n % 3 <> 0
AND T2.n < 1 + T1.n % 15
PRINT '
COUNT Version:
'
WAITFOR DELAY '00:00:01'
SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT
T1.ID
, CASE WHEN n > 0 THEN 1 ELSE 0 END AS DoesExist
FROM @tmp1 AS T1
LEFT JOIN (
SELECT
T2.ID
, COUNT(*) AS n
FROM @tmp2 AS T2
GROUP BY T2.ID
) AS T2 ON (
T2.ID = T1.ID
)
WHERE T1.ID BETWEEN 5000 AND 7000
OPTION (RECOMPILE) -- Required since table are filled within the same scope
SET STATISTICS TIME OFF
PRINT '
EXISTS Version:'
WAITFOR DELAY '00:00:01'
SET STATISTICS TIME ON
SELECT
T1.ID
, CASE WHEN EXISTS (
SELECT 1
FROM @tmp2 AS T2
WHERE T2.ID = T1.ID
) THEN 1 ELSE 0 END AS DoesExist
FROM @tmp1 AS T1
WHERE T1.ID BETWEEN 5000 AND 7000
OPTION (RECOMPILE) -- Required since table are filled within the same scope
SET STATISTICS TIME OFF
ใน SQL Server 2008R2 (เซเว่น 64 บิต) ฉันได้รับผลนี้
COUNT
เวอร์ชัน:
ตาราง '# 455F344D' จำนวนการสแกน 1, การอ่านเชิงตรรกะ 8, การอ่านทางกายภาพ 0, การอ่านล่วงหน้าอ่าน 0, การอ่านตรรกะล่วงหน้า lob 0, lob ทางกายภาพอ่าน 0, lob การอ่านล่วงหน้าอ่าน 0
ตาราง '# 492FC531' จำนวนการสแกน 1, อ่านโลจิคัล 30, อ่านฟิสิคัล 0, อ่านล่วงหน้าอ่าน 0, โลจิคัลล็อกอ่าน 0, lob อ่านฟิสิคัล 0, อ่านล็อบล่วงหน้าอ่าน 0เวลาดำเนินการของ SQL Server:
เวลา CPU = 0 ms, เวลาที่ผ่านไป = 81 ms
EXISTS
เวอร์ชัน:
ตาราง '# 492FC531' จำนวนการสแกน 1, การอ่านแบบลอจิคัล 96, การอ่านแบบฟิสิคัล 0, การอ่านล่วงหน้าอ่าน 0, การอ่านแบบลอจิคัล lob 0, lob ทางกายภาพอ่าน 0, lob การอ่านล่วงหน้าอ่าน 0
ตาราง '# 455F344D' จำนวนการสแกน 1, การอ่านเชิงตรรกะ 8, การอ่านทางกายภาพ 0, การอ่านล่วงหน้าอ่าน 0, lob ตรรกะอ่าน 0, lob การอ่านทางกายภาพ 0, lob การอ่านล่วงหน้าอ่าน 0เวลาดำเนินการของ SQL Server:
เวลา CPU = 0 ms, เวลาที่ผ่านไป = 76 ms