2010-01-25 12 views
6

Mam tabeli Oracle o rekordowej liczby 99896618.Oracle & Pagination

muszę sprowadzić małą porcję danych (powiedzmy 100 rekordów), aby pokazać go na stronie internetowej (w WEB świata możemy nazwać stronicowanie). Obecnie używam następującego zapytania, aby to osiągnąć, jednak użytkownicy nie są zadowoleni z wydajności.

SELECT * FROM (select rownum rnum,f.* from findings f where rownum<90000100) 
        WHERE rnum > 90000000 

Obecnie zajmuje to 1 minutę 22 sekundy, aby uzyskać wyniki. Czy tak jest, żeby było lepiej. Jestem z pewnością otwarty na wszelkie sugestie, w tym modyfikowanie struktury tabeli lub dodawanie indeksów.

(Właśnie FYI, używam ASP.NET jak po stronie serwera technologii internetowej i ADO.NET jako warstwa dostępu do danych i Silverlight do prezentacji po stronie klienta)

Odpowiedz

6

Twoje zapytanie będzie wymagało odliczenia pierwszych rekordów 90M, aby uzyskać kolejne 100, więc nie ma miejsca na poprawę.

Nie widzę klauzuli ORDER BY w podkwerendie, ale prawdopodobnie ją masz. W takim przypadku możesz utworzyć na nim indeks.

Pytanie brzmi: czy Twoi użytkownicy naprawdę klikają na strony 900K, zanim narzekają na wydajność?

Aktualizacja:

Jeśli potrzebujesz ostatnią stronę, trzeba przepisać swoją kolumnę ORDER BY w porządku malejącym:

SELECT * 
FROM (
     SELECT rownum rnum, f.* 
     FROM findings f 
     ORDER BY 
       record_ordering_column DESC 
     ) 
WHERE rnum > 900 
     AND rownum <= 100 

i utworzyć indeks na record_ordering_column

pamiętać, że zmiksuj rownum z zagnieżdżonych zapytań, aby poprawić wydajność.

Zobacz artykuł w moim blogu dla bardziej szczegółowo:

+0

Udostępniłem numer strony łatwo dostępny, tworząc listę rozwijaną numerów stron (tylko uproszczony opis, stworzyłem niestandardową kontrolę, dzięki której mogą łatwo uzyskać dostęp do ostatnich 1000 stron). Może to być przydatne informacje, przez większość czasu (około 95% czasu) użytkownicy są zainteresowani ostatnimi (najnowszymi) rekordami. – funwithcoding

1

Jeśli są chętni, aby zmodyfikować tabelę I sugeruje, że dodajesz kolumnę rownumber do tabeli (przy użyciu wyzwalacza wstawiania i sekwencji do ustawienia), a następnie dodajesz indeks do tej kolumny.

+0

W Oracle nie ma indeksów klastrowych ani klastrowych - nazywa się je tylko indeksami. –

+0

'' '' Kucyki @OMG': tak, ale są indeksowane klastry w 'Oracle'! :) – Quassnoi

+0

Kucyki @OMG: Klucz podstawowy to indeks klastrowany w Oracle i wszystkie indeksy kluczy podstawowych nie są klastrowane. Musisz mówić o "nieklastrowanym" * słowie kluczowym *, o którym wiem, że nie istnieje w wyroczni. –

5

z jednego z komentarzy:

większość czasu (około 95% czasu) użytkownicy są zainteresowani ostatnimi rekordami (najnowszymi)

W takim przypadku, dlaczego nie wyświetlać rekordów w odwrotnej kolejności, tak aby 95% czasu użytkownicy byli zainteresowani stroną 1 zamiast stroną 900 000?

Jeśli naprawdę chcą widzieć "stronę 900 000", oznacza to, że interesują się danymi z dawno temu, więc pozwól im filtrować dane przez np. zakres dat. Przeczesanie 100 milionów wierszy bez filtrowania nigdy nie będzie wydajne.

0

Czy naprawdę potrzebujesz odzyskać cały rząd?Oznacza to, że nie używasz żadnych indeksów.

Jeśli nadal potrzebujesz całego rzędu. Użyj następującego wzoru:

SELECT * FROM findings f1 WHERE f1.rowid IN 
    (SELECT rownum rnum, row_id 
     FROM (
      SELECT f.rowid row_id 
       FROM findings f 
      ORDER BY record_ordering_column 
      ) 
    WHERE rownum > 900 
    ) 
WHERE rnum <= 100; 

Zobacz

Uwaga: subtelne dodatkowa klauzula SELECT, a także za pomocą zapytań ROWID.

Jeśli dodasz indeks do kolumny nazwa_korda, wówczas pogaństwo użyje indeksu do uzyskania zestawu identyfikatorów ROWID. Następnie załaduj tylko bloki zawierające wiersze zidentyfikowane przez ich ROWIDs.

To będzie lepsze niż bieżące zapytanie, które będzie pełnym skanowaniem tabeli.