Както други вече посочиха, заявките връщат различни резултати и сравняват ябълки с портокали.
Но основният въпрос остава:кое е по-бързо:пейджиране, управлявано от набор от клавиши, или пейджиране, управлявано от номера на ред?
Пейджинг на клавишите
Страничната страница, управлявана от набор от клавиши, разчита на запомнянето на горния и долния клавиш на последната показана страница и изискване на следващия или предишен набор от редове въз основа на горния/последния набор от ключове:
Следваща страница:
select top (<pagesize>) ...
from <table>
where key > @last_key_on_current_page
order by key;
Предишна страница:
select top (<pagesize>)
from <table>
where key < @first_key_on_current_page
order by key desc;
Този подход има две основни предимства пред подхода ROW_NUMBER или пред еквивалентния LIMIT подход на MySQL:
- еправилно :за разлика от подхода, базиран на номера на редове, той правилно обработва нови записи и изтрити записи. Последният ред на страница 4 не се показва като първи ред на страница 5, само защото ред 23 на страница 2 беше изтрит междувременно. Нито пък редовете мистериозно изчезват между страниците. Тези аномалии са често срещани при подхода, базиран на row_number, но решението, базирано на набор от ключове, върши много по-добра работа при избягването им.
- ебърз :всички операции могат да бъдат решени с бързо позициониране на редове, последвано от сканиране на диапазон в желаната посока
Този подход обаче етруден за изпълнение, трудно разбираемо от обикновения програмист и не се поддържа от инструментите.
Управляван номер на ред
Това е общият подход, въведен със заявките на Linq:
select ...
from (
select ..., row_number() over (...) as rn
from table)
where rn between @firstRow and @lastRow;
(или подобна заявка, използваща TOP) Този подход е лесен за внедряване и се поддържа от инструменти (по-специално от операторите Linq .Limit и .Take). Но този подход е гарантиран за да сканирате индекса, за да преброите редовете. Този подход обикновено работи много бързо за страница 1 и постепенно се забавя, когато едната преминава към все по-високи номера на страници.
Като бонус, с това решение е много лесно да промените реда на сортиране (просто променете клаузата OVER).
Като цяло, като се има предвид лекотата на решенията, базирани на ROW_NUMBER(), подкрепата, която имат от Linq, простотата за използване на произволни поръчки за умерени набори от данни базираните на ROW_NUMBER решения са подходящи. За големи и много големи набори от данни ROW_NUMBER() може да възникне сериозни проблеми с производителността.
Друго нещо, което трябва да имате предвид, е, че често има определен модел на достъп. Често първите няколко страници са горещи и страници след 10 по принцип никога не се разглеждат (напр. най-новите публикации). В този случай наказанието, което настъпва с ROW_NUMBER() за посещение на най-долните страници (показване на страници, за които трябва да се преброят голям брой редове, за да се получи началният ред с резултати), може да бъде добре игнорирано.
И накрая, пагинацията на набора от клавиши е чудесна за навигация в речник, която ROW_NUMBER() не може лесно да поеме. Навигацията в речника е мястото, където вместо да използват номера на страницата, потребителите могат да навигират до определени котви, като букви от азбуката. Типичен пример е странична лента за контакт с Rolodex, щракнете върху M и отидете до името на първия клиент, което започва с M.