Contoh-contoh dalam pertanyaan tidak cukup menghasilkan hasil yang sama ( OFFSETcontoh memiliki kesalahan off-by-one). Formulir yang diperbarui di bawah memperbaiki masalah itu, menghapus jenis tambahan untuk ROW_NUMBERkasus 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_NUMBERtersebut memiliki perkiraan biaya 0,0197935 :

Paket OFFSETtersebut memiliki perkiraan biaya 0,0196955 :

Itu adalah penghematan 0,000098 unit biaya yang diperkirakan (meskipun OFFSETpaket 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 30dalam 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 OFFSETdan 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_NUMBERpola 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
OFFSETrencana 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 OFFSETatau 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.