Contoh-contoh dalam pertanyaan tidak cukup menghasilkan hasil yang sama ( OFFSET
contoh memiliki kesalahan off-by-one). Formulir yang diperbarui di bawah memperbaiki masalah itu, menghapus jenis tambahan untuk ROW_NUMBER
kasus ini, dan menggunakan variabel untuk membuat solusi lebih umum:
DECLARE
@PageSize bigint = 10,
@PageNumber integer = 3;
WITH Numbered AS
(
SELECT TOP ((@PageNumber + 1) * @PageSize)
o.*,
rn = ROW_NUMBER() OVER (
ORDER BY o.[object_id])
FROM #objects AS o
ORDER BY
o.[object_id]
)
SELECT
x.name,
x.[object_id],
x.principal_id,
x.[schema_id],
x.parent_object_id,
x.[type],
x.type_desc,
x.create_date,
x.modify_date,
x.is_ms_shipped,
x.is_published,
x.is_schema_published
FROM Numbered AS x
WHERE
x.rn >= @PageNumber * @PageSize
AND x.rn < ((@PageNumber + 1) * @PageSize)
ORDER BY
x.[object_id];
SELECT
o.name,
o.[object_id],
o.principal_id,
o.[schema_id],
o.parent_object_id,
o.[type],
o.type_desc,
o.create_date,
o.modify_date,
o.is_ms_shipped,
o.is_published,
o.is_schema_published
FROM #objects AS o
ORDER BY
o.[object_id]
OFFSET @PageNumber * @PageSize - 1 ROWS
FETCH NEXT @PageSize ROWS ONLY;
Paket ROW_NUMBER
tersebut memiliki perkiraan biaya 0,0197935 :
Paket OFFSET
tersebut memiliki perkiraan biaya 0,0196955 :
Itu adalah penghematan 0,000098 unit biaya yang diperkirakan (meskipun OFFSET
paket tersebut akan membutuhkan operator tambahan jika Anda ingin mengembalikan nomor baris untuk setiap baris). ItuOFFSET
rencana masih akan sedikit lebih murah, secara umum, tapi ingat bahwa estimasi biaya persis bahwa - pengujian nyata masih diperlukan. Sebagian besar biaya dalam kedua paket adalah biaya jenis input yang lengkap, sehingga indeks yang bermanfaat akan menguntungkan kedua solusi.
Di mana nilai literal konstan digunakan (misalnya OFFSET 30
dalam contoh asli) pengoptimal dapat menggunakan Sortasi TopN alih-alih pengurutan lengkap diikuti oleh Top. Ketika baris yang diperlukan dari Sort TopN adalah literal konstan dan <= 100 (jumlah OFFSET
dan FETCH
) mesin eksekusi dapat menggunakan algoritma sort yang berbeda yang dapat melakukan lebih cepat daripada sortasi TopN yang digeneralisasi. Ketiga kasus memiliki karakteristik kinerja yang berbeda secara keseluruhan.
Mengapa pengoptimal tidak secara otomatis mengubah ROW_NUMBER
pola sintaksis untuk digunakan OFFSET
, ada beberapa alasan:
- Hampir tidak mungkin untuk menulis transformasi yang akan cocok dengan semua kegunaan yang ada
- Memiliki beberapa kueri paging secara otomatis berubah dan tidak yang lain dapat membingungkan
- The
OFFSET
rencana tidak dijamin untuk menjadi lebih baik dalam semua kasus
Salah satu contoh untuk titik ketiga di atas terjadi di mana set paging cukup lebar. Ini bisa menjadi jauh lebih efisien untuk mencari kunci yang diperlukan menggunakan indeks nonclustered dan pencarian secara manual terhadap indeks berkerumun dibandingkan dengan memindai indeks dengan OFFSET
atau ROW_NUMBER
. Ada masalah tambahan untuk dipertimbangkan jika aplikasi paging perlu tahu berapa banyak baris atau halaman yang ada secara total. Ada diskusi bagus lainnya tentang manfaat relatif dari metode 'pencarian kunci' dan 'offset' di sini .
Secara keseluruhan, mungkin lebih baik bahwa orang membuat keputusan untuk mengubah permintaan halaman mereka OFFSET
, jika perlu, setelah pengujian menyeluruh.