Bu akış neden gereklidir?


12

Bu sorguyu kontrol edin. Oldukça basit (tablo ve dizin tanımları ve repro komut dosyası için gönderinin sonuna bakın):

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

Not: "VE 1 = (SEÇ 1), bu sorgunun sorunu otomatik olarak değiştirdiğini ve bununla ilgili kafa karıştırıcı olduğunu hissettiğimi korumaktır - aslında aynı planı olsa da olmasa da aynı planı alır

Ve işte plan ( plan bağlantısını yapıştırın) :

bir akış agg ile planlayın

Orada bir "ilk 1" olduğundan, akış toplama operatörü görmek için sürpriz oldu. Benim için gerekli görünmüyor, çünkü sadece bir sıra olması garanti ediliyor.

Bu teoriyi test etmek için, bu mantıksal olarak eşdeğer sorguyu denedim:

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

İşte bunun için plan ( plan bağlantısını yapıştırın ):

akış agg olmadan planlama

Tabii ki, plana göre grup akışı toplama operatörü olmadan geçebilir.

Her iki sorgunun dizinin sonundan "geriye" okuduğuna ve maksimum revizyonu almak için "ilk 1" e dikkat edin.

Burada ne eksik? Akış toplamı ilk sorguda gerçekten çalışıyor mu yoksa ortadan kaldırılabiliyor mu (ve optimize edilmeyen bir kısıtlama değil mi)?

Bu arada, bunun inanılmaz derecede pratik bir sorun olmadığını fark ediyorum (her iki sorgu da 0 ms CPU ve geçen süreyi rapor ediyor), sadece burada sergilenen iç / davranışları merak ediyorum.


Yukarıdaki iki sorguyu çalıştırmadan önce çalıştırdığım kurulum kodu:

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

Yanıtlar:


16

Cümle ile eşleşen satır yoksa, bu toplamın rolünü görebilirsiniz WHERE.

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

Bu durumda, sıfır satır toplam içine girer, ancak yine de doğru semantik NULLbu durumda dönmek için bir tane yayar .

resim açıklamasını buraya girin

Bu bir vektörün aksine skaler bir agregadır.

"Mantıksal olarak eşdeğer" sorgunuz eşdeğer değil. Ekleme GROUP BY Idbunu bir vektör toplamı haline getirecek ve daha sonra doğru davranış hiçbir satır döndürmemek olacaktır.

Bu konuda daha fazla bilgi için Skaler ve Vektör Kümeleriyle Eğlence konusuna bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.