sql >> Databáze >  >> RDS >> Sqlserver

Výkon SQL:WHERE vs. WHERE (ROW_NUMBER)

Jak již uvedli jiní, dotazy vracejí různé výsledky a porovnávají jablka s pomeranči.

Základní otázkou však zůstává:co je rychlejší:stránkování řízené sadou klíčů nebo stránkování řízené počtem řádků?

Stránka sady kláves

Stránkování řízené sadou kláves spoléhá na zapamatování horních a dolních kláves poslední zobrazené stránky a vyžádání další nebo předchozí sady řádků na základě horní/poslední sady kláves:

Další stránka:

select top (<pagesize>) ...
from <table>
where key > @last_key_on_current_page
order by key;

Předchozí stránka:

select top (<pagesize>)
from <table>
where key < @first_key_on_current_page
order by key desc;

Tento přístup má dvě hlavní výhody oproti přístupu ROW_NUMBER nebo oproti ekvivalentnímu LIMIT přístupu MySQL:

  • je správné :na rozdíl od přístupu založeného na počtu řádků správně zpracovává nové záznamy a odstraněné záznamy. Poslední řádek stránky 4 se nezobrazuje jako první řádek stránky 5 jen proto, že řádek 23 na stránce 2 byl mezitím smazán. Ani řádky mezi stránkami záhadně nemizí. Tyto anomálie jsou běžné u přístupu založeného na row_number, ale řešení založené na množině klíčů odvádí mnohem lepší práci při jejich předcházení.
  • je rychlý :všechny operace lze vyřešit rychlým umístěním řádků následovaným skenováním rozsahu v požadovaném směru

Tento přístup je však obtížný implementovat, pro průměrného programátora těžko pochopitelné a nepodporované nástroji.

Řízeno číslem řádku

Toto je běžný přístup představený u dotazů Linq:

select ...
from (
  select ..., row_number() over (...) as rn
  from table)
where rn between @firstRow and @lastRow;

(nebo podobný dotaz pomocí TOP)Tento přístup je snadný implementovat a je podporován nástroji (konkrétně operátory Linq .Limit a .Take). Tento přístup je ale zaručený pro skenování indexu za účelem počítání řádků. Tento přístup obvykle funguje velmi rychle pro stránku 1 a postupně se zpomaluje, jak se jednička dostává na vyšší a vyšší čísla stránek.

Jako bonus je s tímto řešením velmi snadné změnit pořadí řazení (stačí změnit klauzuli OVER).

Celkově vzato, vzhledem k jednoduchosti řešení založených na ROW_NUMBER(), podpoře, kterou mají od Linq, jednoduchosti použití libovolných objednávek pro střední datové sady řešení založená na ROW_NUMBER jsou adekvátní. U velkých a velmi velkých souborů dat může ROW_NUMBER() nastat vážné problémy s výkonem.

Další věcí, kterou je třeba zvážit, je, že často existuje určitý vzor přístupu. Prvních pár stránek je často horkých a stránky po 10 se v podstatě nikdy nezobrazují (např. nejnovější příspěvky). V tomto případě může být penalizace, ke které dochází u ROW_NUMBER() za návštěvu spodních stránek (zobrazené stránky, pro které je třeba napočítat velký počet řádků, aby se získal řádek s počátečním výsledkem), dobře ignorována.

A konečně stránkování sady klíčů je skvělé pro navigaci ve slovníku, kterou ROW_NUMBER() nemůže snadno pojmout. Navigace ve slovníku je místo, kde uživatelé mohou namísto čísla stránky přejít na určité kotvy, jako jsou písmena abecedy. Typickým příkladem je kontaktní Rolodex jako postranní panel, kliknete na M a přejdete na jméno prvního zákazníka, které začíná na M.



  1. Jak zobrazit znaky UTF-8 v phpMyAdmin?

  2. Úvahy o pořadí sloupců v indexech a řazení

  3. Jedinečné omezení na kombinaci dvou sloupců?

  4. Použití seskupení podle dvou polí a počítání v SQL