Jaki jest najlepszy (pod względem wydajności) sposób stronicowania wyników w SQL Server 2000, 2005, 2008, 2012, jeśli chcesz również uzyskać całkowitą liczbę wyników (przed paginowaniem)?
sql
sql-server
performance
pagination
Panagiotis Korros
źródło
źródło
Odpowiedzi:
Uzyskiwanie całkowitej liczby wyników i dzielenie na strony to dwie różne operacje. Na potrzeby tego przykładu załóżmy, że zapytanie, którym się zajmujesz, jest
W takim przypadku możesz określić całkowitą liczbę wyników, używając:
... co może wydawać się nieefektywne, ale w rzeczywistości jest dość wydajne, zakładając, że wszystkie indeksy itp. są poprawnie skonfigurowane.
Następnie, aby uzyskać rzeczywiste wyniki z powrotem w sposób stronicowany, najbardziej wydajne byłoby następujące zapytanie:
Zwróci to wiersze 1-19 pierwotnego zapytania. Fajną rzeczą, szczególnie w przypadku aplikacji internetowych, jest to, że nie musisz utrzymywać żadnego stanu, z wyjątkiem numerów wierszy, które mają zostać zwrócone.
źródło
Wreszcie Microsoft SQL Server 2012 został wydany, bardzo podoba mi się jego prostota w przypadku paginacji, nie musisz używać skomplikowanych zapytań, takich jak odpowiedzi tutaj.
Aby uzyskać kolejne 10 wierszy, wystarczy uruchomić to zapytanie:
https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql#using-offset-and-fetch-to-limit-the-rows- zwrócony
Najważniejsze kwestie, które należy wziąć pod uwagę podczas jego używania:
ORDER BY
jest obowiązkowe, aby użyćOFFSET ... FETCH
klauzuli.OFFSET
klauzula jest obowiązkowa zFETCH
. Nie możesz użyćORDER BY ... FETCH
.TOP
nie może być połączony zOFFSET
iFETCH
w tym samym ekspresję zapytania.źródło
LISTAGG()
/GROUP_CONCAT()
.FOR XML
: stackoverflow.com/a/273330/429949FOR XML PATH ('')
. Po pierwsze, zastępuje znaki sterujące XML kodami encji XML. Nadzieję, że nie masz<
,>
albo&
w danych! Po drugie,FOR XML PATH ('')
w ten sposób używana jest nieudokumentowana składnia. Musisz podać nazwaną kolumnę lub alternatywną nazwę elementu. Nie robienie tego nie jest w dokumencie, co oznacza, że zachowanie jest zawodne. Po trzecie, im bardziej akceptujemy zepsutąFOR XML PATH ('')
składnię, tym mniej prawdopodobne jest, że stwardnienie rozsiane zapewnia rzeczywistąLISTAGG() [ OVER() ]
funkcję taką, jaką musieli.Niesamowicie, żadna inna odpowiedź nie wspomina o najszybszym sposobie podziału na strony we wszystkich wersjach SQL Server. Przesunięcia mogą być strasznie powolne w przypadku dużych numerów stron, co jest tutaj testowane . Istnieje całkowicie inny, znacznie szybszy sposób wykonywania paginacji w SQL. Jest to często nazywane „metodą wyszukiwania” lub „paginacją zestawu kluczy”, jak opisano w tym poście na blogu tutaj .
„Predicate seek”
Wartości
@previousScore
i@previousPlayerId
są odpowiednimi wartościami ostatniego rekordu z poprzedniej strony. Pozwala to pobrać „następną” stronę. JeśliORDER BY
kierunek jestASC
, po prostu użyj>
zamiast tego.Przy użyciu powyższej metody nie można od razu przejść do strony 4 bez uprzedniego pobrania 40 poprzednich rekordów. Ale często i tak nie chcesz skakać tak daleko. Zamiast tego otrzymujesz znacznie szybsze zapytanie, które może być w stanie pobrać dane w stałym czasie, w zależności od twojego indeksowania. Ponadto strony pozostają „stabilne”, bez względu na to, czy zmieniają się dane bazowe (np. Na stronie 1, gdy jesteś na stronie 4).
Jest to najlepszy sposób na wdrożenie paginacji, gdy na przykład leniwe ładowanie większej ilości danych w aplikacjach internetowych.
Uwaga: „metoda wyszukiwania” nazywana jest również paginacją zestawu kluczy .
Suma rekordów przed paginacją
Funkcja
COUNT(*) OVER()
okna pomoże ci policzyć całkowitą liczbę rekordów „przed paginacją”. Jeśli używasz programu SQL Server 2000, będziesz musiał skorzystać z dwóch zapytań dotyczącychCOUNT(*)
.źródło
OFFSET .. FETCH
, czy w poprzednichROW_NUMBER()
sztuczkach.RowNumber
daje mi spójne 10 pozycji na stronie. [3] nie działa z istniejącymi siatkami, które zakładająpagenumber
ipagesize
.Od SQL Server 2012 możemy użyć
OFFSET
iFETCH NEXT
Clause, aby osiągnąć podział na strony.Wypróbuj to, dla SQL Server:
TechNet: Stronicowanie zapytania za pomocą programu SQL Server
źródło
MSDN: ROW_NUMBER (Transact-SQL)
źródło
Dobry przegląd różnych technik stronicowania znajduje się na stronie http://www.codeproject.com/KB/aspnet/PagingLarge.aspx
Stosowałem metodę ROWCOUNT dość często głównie z SQL Server 2000 (będzie również działać w 2005 i 2008 roku, po prostu mierz wydajność w porównaniu do ROW_NUMBER), jest błyskawiczny, ale musisz się upewnić, że posortowane kolumny mają (głównie ) unikalne wartości.
źródło
W przypadku SQL Server 2000 można symulować ROW_NUMBER () przy użyciu zmiennej tabeli z kolumną TOŻSAMOŚĆ:
Podejście to można rozszerzyć na tabele z kluczami wielokolumnowymi i nie wiąże się to z dodatkowym obciążeniem związanym z używaniem OR (co pomija użycie indeksu). Minusem jest ilość tymczasowego miejsca zużytego, jeśli zestaw danych jest bardzo duży i jeden znajduje się w pobliżu ostatniej strony. W tym przypadku nie testowałem wydajności kursora, ale może być lepiej.
Pamiętaj, że to podejście można zoptymalizować dla pierwszej strony danych. Ponadto zastosowano ROWCOUNT, ponieważ TOP nie akceptuje zmiennej w SQL Server 2000.
źródło
Najlepszym sposobem stronicowania na serwerze SQL 2012 jest użycie przesunięcia i pobierania dalej w procedurze składowanej. Słowo kluczowe PRZESUNIĘCIE - Jeśli użyjemy przesunięcia względem kolejności według klauzuli, wówczas zapytanie pominie liczbę rekordów określoną w PRZESUNIĘCIE n Wiersze.
FETCH NEXT Słowa kluczowe - gdy używamy Fetch Next tylko z klauzulą porządkującą, zwraca tylko liczbę wierszy, które chcesz wyświetlić w stronicowaniu, bez przesunięcia, wówczas SQL wygeneruje błąd. oto przykład podany poniżej.
możesz wykonać to w następujący sposób.
źródło
To są moje rozwiązania do stronicowania wyniku zapytania po stronie serwera SQL. te podejścia są różne w SQL Server 2008 i 2012. Ponadto dodałem koncepcję filtrowania i porządkowania według jednej kolumny. Jest bardzo wydajny, gdy stronicujesz, filtrujesz i porządkujesz w swoim Gridview.
Przed testowaniem musisz utworzyć jedną przykładową tabelę i wstawić wiersz w tej tabeli: (W prawdziwym świecie musisz zmienić klauzulę Where, biorąc pod uwagę pola tabeli i być może masz trochę sprzężenia i podzapytania w głównej części select)
We wszystkich tych przykładach chcę wykonać zapytanie do 200 wierszy na stronę i pobieram wiersz dla strony o numerze 1200.
W SQL Server 2008 możesz użyć koncepcji CTE. Z tego powodu napisałem dwa typy zapytań dla SQL Server 2008+
- SQL Server 2008+
I drugie rozwiązanie z CTE w SQL Server 2008+
- SQL Server 2012+
źródło
Wypróbuj to podejście:
źródło
Przypadki użycia wydają się łatwe w użyciu i szybkie. Wystarczy ustawić numer strony.
także bez CTE
źródło
Cóż, użyłem następującego przykładowego zapytania w mojej bazie danych SQL 2000, działa również dobrze dla SQL 2005. Moc, którą daje, jest dynamicznie uporządkowana za pomocą wielu kolumn. Mówię ci ... to jest potężne :)
Najlepszą częścią jest sp_executesql buforuje późniejsze wywołania, pod warunkiem, że przekazujesz te same parametry, tj. Generujesz ten sam tekst sql.
źródło
zrestartuje idx, jeśli chodzi o inny init_id
źródło
W przypadku tej
ROW_NUMBER
techniki, jeśli nie masz kolumny do sortowania, możesz użyćCURRENT_TIMESTAMP
następujących opcji:Działa to dla mnie dobrze w przypadku wyszukiwań powyżej rozmiarów tabel nawet do 700 000.
Pobiera rekordy od 11 do 30.
źródło
źródło
Ten bit daje możliwość stronicowania przy użyciu SQL Server i nowszych wersji MySQL i przenosi całkowitą liczbę wierszy w każdym wierszu. Używa klucza podstawowego, aby policzyć liczbę unikalnych wierszy.
źródło
Jest to duplikat starego pytania SO z 2012 r .: efektywny sposób wdrażania stronicowania
Tutaj temat jest omawiany bardziej szczegółowo i przy alternatywnym podejściu.
źródło
Od 2012 roku możemy korzystać
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
źródło
Nie określono języka ani używanego sterownika. Dlatego opisuję to abstrakcyjnie.
źródło