Saya menulis di posting blog saya yang akan datang tentang fungsi peringkat dan jendela agregat, khususnya iterator Segment and Sequence Project. Cara saya memahaminya adalah bahwa Segmen mengidentifikasi baris dalam aliran yang merupakan akhir / awal grup, jadi pertanyaan berikut:
SELECT ROW_NUMBER() OVER (PARTITION BY someGroup ORDER BY someOrder)
Akan menggunakan Segmen untuk memberi tahu kapan baris milik grup lain selain dari baris sebelumnya. Iterator Proyek Urutan kemudian melakukan perhitungan angka baris aktual, berdasarkan output dari output iterator Segmen.
Tetapi kueri berikut, menggunakan logika itu, tidak harus menyertakan Segmen, karena tidak ada ekspresi partisi.
SELECT ROW_NUMBER() OVER (ORDER BY someGroup, someOrder)
Namun, ketika saya mencoba hipotesis ini, kedua kueri ini menggunakan operator Segmen. Satu-satunya perbedaan adalah bahwa permintaan kedua tidak perlu GroupBy
pada Segmen. Bukankah itu menghilangkan kebutuhan untuk Segmen di tempat pertama?
Contoh
CREATE TABLE dbo.someTable (
someGroup int NOT NULL,
someOrder int NOT NULL,
someValue numeric(8, 2) NOT NULL,
PRIMARY KEY CLUSTERED (someGroup, someOrder)
);
--- Query 1:
SELECT ROW_NUMBER() OVER (PARTITION BY someGroup ORDER BY someOrder)
FROM dbo.someTable;
--- Query 2:
SELECT ROW_NUMBER() OVER (ORDER BY someGroup, someOrder)
FROM dbo.someTable;
sumber
<GroupBy />
sehingga segmen benar-benar tidak melakukan apa-apa, hampir, ia mengeluarkan kolom segmen ke operator Proyek Urutan. Alasan bagi operator segmen untuk berada di sana mungkin karena operator Proyek Urutan membutuhkan nilai tersebut untuk melakukan tugasnya.Jawaban:
Saya menemukan posting blog berusia 6 tahun ini menyebutkan perilaku yang sama.
Sepertinya
ROW_NUMBER()
selalu menyertakan operator segmen, apakahPARTITION BY
digunakan atau tidak. Jika saya harus menebak saya akan mengatakan ini karena itu membuat membuat rencana permintaan lebih mudah di mesin.Jika segmen diperlukan dalam kebanyakan kasus, dan dalam kasus di mana tidak diperlukan pada dasarnya itu adalah non-operasi tanpa biaya, itu jauh lebih mudah untuk selalu memasukkannya ke dalam rencana ketika fungsi windowing digunakan.
sumber
Menurut showplan.xsd untuk rencana eksekusi,
GroupBy
muncul tanpaminOccurs
ataumaxOccurs
atribut yang karenanya standar untuk [1..1] membuat elemen wajib, tidak harus konten. Elemen turunanColumnReference
dari type (ColumnReferenceType
) memilikiminOccurs
0 dan tidakmaxOccurs
terikat [0 .. *], menjadikannya opsional , karenanya elemen kosong yang diizinkan. Jika Anda mencoba untuk menghapusGroupBy
dan memaksa paket secara manual, Anda mendapatkan kesalahan yang diharapkan:Menariknya saya menemukan Anda dapat secara manual menghapus operator Segmen untuk mendapatkan rencana pemaksaan yang berlaku yang terlihat seperti ini:
Namun ketika Anda menjalankan dengan rencana itu (menggunakan
OPTION ( USE PLAN ... )
) Operator Segmen muncul kembali secara ajaib. Hanya untuk menunjukkan pengoptimal hanya mengambil rencana XML sebagai panduan kasar.Rig pengujian saya:
Memotong rencana XML dari rig uji dan menyimpannya sebagai .sqlplan untuk melihat paket minus Segmen.
PS Saya tidak akan menghabiskan terlalu banyak waktu memotong-motong rencana SQL secara manual seolah-olah Anda tahu saya, Anda akan tahu saya menganggapnya sebagai pekerjaan yang sibuk memakan waktu dan sesuatu yang tidak akan pernah saya lakukan. Oh, tunggu !? :)
sumber