เหตุใดกระแสรวมนี้จึงมีความจำเป็น


12

ลองดูคำถามนี้ มันค่อนข้างง่าย (ดูจุดสิ้นสุดของการโพสต์สำหรับคำจำกัดความของตารางและดัชนีและสคริปต์ที่ซ้ำกัน):

SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1 AND 1 = (SELECT 1);

หมายเหตุ: "AND 1 = (SELECT 1) เพียงเพื่อป้องกันไม่ให้มีการกำหนดพารามิเตอร์อัตโนมัติซึ่งฉันรู้สึกว่าสับสนปัญหา - จริง ๆ แล้วได้รับแผนเดียวกันโดยมีหรือไม่มีประโยคนั้นแม้ว่า

และนี่คือแผน ( วางลิงก์แผน) :

วางแผนด้วยสตรีม agg

เนื่องจากมี "อันดับ 1" อยู่ที่นั่นฉันรู้สึกประหลาดใจที่เห็นผู้ดำเนินการรวมสตรีม ไม่จำเป็นสำหรับฉันเนื่องจากมีการรับประกันว่าจะมีแถวเดียวเท่านั้น

เพื่อทดสอบทฤษฎีนั้นฉันลองใช้เคียวรีที่มีเหตุผลเชิงตรรกะนี้:

SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1
GROUP BY Id;

นี่คือแผนสำหรับแผนนั้น ( วางลิงก์แผน ):

วางแผนโดยไม่ต้องสตรีม agg

แน่นอนกลุ่มตามแผนสามารถรับได้โดยไม่ต้องมีผู้ดำเนินการรวมสตรีม

โปรดสังเกตว่าแบบสอบถามทั้งสองอ่าน "ย้อนกลับ" จากจุดสิ้นสุดของดัชนีและทำ "อันดับ 1" เพื่อรับการแก้ไขสูงสุด

ฉันหายไปนี่อะไร สตรีมที่รวมทำงานจริง ๆ ในแบบสอบถามแรกหรือไม่หรือควรถูกกำจัด (และเป็นเพียงข้อ จำกัด ของเครื่องมือเพิ่มประสิทธิภาพที่ไม่ใช่)

โดยวิธีการที่ฉันรู้ว่านี่ไม่ใช่ปัญหาในทางปฏิบัติอย่างเหลือเชื่อ (แบบสอบถามทั้งสองรายงาน 0 ms ของ CPU และเวลาที่ผ่านไป) ฉันแค่อยากรู้เกี่ยวกับ internals / พฤติกรรมที่มีการจัดแสดงที่นี่


นี่คือรหัสการตั้งค่าที่ฉันเรียกใช้ก่อนเรียกใช้คำสั่งสองข้อด้านบน:

DROP TABLE IF EXISTS dbo.TheOneders;
GO

CREATE TABLE dbo.TheOneders
(
    Id INT NOT NULL,
    Revision SMALLINT NOT NULL,
    Something NVARCHAR(23),

    CONSTRAINT PK_TheOneders PRIMARY KEY NONCLUSTERED (Id, Revision)
);
GO

INSERT INTO dbo.TheOneders
    (Id, Revision, Something)
SELECT DISTINCT TOP 1000 
    1, m.message_id, 'Do...'
FROM sys.messages m
ORDER BY m.message_id
OPTION (MAXDOP 1);

INSERT INTO dbo.TheOneders
    (Id, Revision, Something)
SELECT DISTINCT TOP 100 
    2, m.message_id, 'Do that thing you do...'
FROM sys.messages m
ORDER BY m.message_id
OPTION (MAXDOP 1);
GO

คำตอบ:


16

คุณสามารถเห็นบทบาทของการรวมนี้หากไม่มีแถวที่ตรงกับWHEREอนุประโยค

SELECT MAX(Revision)
FROM   dbo.TheOneders
WHERE  Id = 1
       AND 1 = 1 /*To avoid auto parameterisation*/
       AND Id%3 = 4  /*always false*/

ในกรณีนั้นแถวศูนย์จะเข้าสู่การรวม แต่ยังคงปล่อยออกมาหนึ่งแถวเนื่องจากซีแมนทิกส์ที่ถูกต้องจะส่งคืนNULLในกรณีนี้

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือการรวมสเกลาร์เมื่อเทียบกับเวกเตอร์หนึ่ง

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

ดูความสนุกกับ Scalar และ Vector Aggregatesสำหรับข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้

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