Jak zapewnić klientowi API 1 000 000 wyników bazy danych?

Po moim poprzednim pytaniu:

Używanie "kursorów" do stronicowania w PostgreSQL

Jaki jest dobry sposób na dostarczenie klientowi API 1 000 000 wyników bazy danych?

Obecnie używamy PostgreSQL. Kilka sugerowanych metod:

  • stronicowanie za pomocą kursorów
  • [[11]} stronicowanie za pomocą liczb losowych (Dodaj "większe niż kolejność przez" do każdego zapytania)
  • stronicowanie przy użyciu limitu i offsetu ( rozkłada się dla bardzo dużych zbiorów danych )
  • Zapisz informacje do pliku i pozwól klientowi je pobrać
  • Iteruj wyniki, a następnie opublikuj dane na serwerze klienta
  • zwróć tylko klucze do klienta, a następnie pozwól klientowi żądać obiektów z plików w chmurze, takich jak Amazon S3(nadal może wymagać stronicowania tylko, aby uzyskać nazwy plików).

Co mi nie przyszło do głowy, że jest głupio proste i o wiele lepsze niż każda z tych opcji?

Author: Community, 2012-10-30

2 answers

Tabela ma klucz podstawowy. Wykorzystaj to.

Zamiast LIMIT i OFFSET, wykonaj stronicowanie z filtrem na kluczu głównym. Zasugerowałeś to swoim komentarzem:

Stronicowanie za pomocą liczb losowych (Dodaj "większą niż kolejność przez" do każdego query)

Ale nie ma nic przypadkowego w tym, jak powinieneś to zrobić.

SELECT * FROM big_table WHERE id > $1 ORDER BY id ASC LIMIT $2

Pozwala klientowi określić zarówno parametry, ostatnio widziany identyfikator, jak i liczbę rekordów do pobrania. Twój API będzie musiał albo mieć symbol zastępczy, dodatkowy parametr lub alternatywne Wywołanie dla "fetch the first N IDs", gdzie pomija klauzulę WHERE z zapytania, ale to jest trywialne.

To podejście wykorzystuje dość wydajne skanowanie indeksów, aby uzyskać porządek rekordów, ogólnie unikając sortowania lub konieczności iteracji wszystkich pominiętych rekordów. Klient może zdecydować, ile wierszy chce na raz.

Podejście to różni się od podejścia LIMIT i OFFSET w jeden kluczowy sposób: współbieżne modyfikacja. Jeśli INSERT wejdziesz do tabeli z kluczem niższym niż klucz, który widział już jakiś klient, to takie podejście w ogóle nie zmieni wyników, podczas gdy podejście OFFSET powtórzy wiersz. Podobnie, Jeśli DELETE wiersz o ID niższym niż już widziany, wyniki tego podejścia nie ulegną zmianie, podczas gdy OFFSET pominie niewidoczny wiersz. Nie ma jednak różnicy w przypadku tabel dołączanych tylko z wygenerowanymi kluczami.

Jeśli wiesz z góry, że klient będzie chciał cały zestaw wyników, najskuteczniejszą rzeczą do zrobienia jest wysłanie im całego zestawu wyników bez żadnej z tych firm przywoławczych. To jest miejsce gdzie ja użyłbym kursora. Odczytaj wiersze z DB i wyślij je do klienta tak szybko, jak klient je zaakceptuje. W przypadku wolnego klienta prawdopodobnie przełączyłbym się na stronicowanie (jak opisano powyżej) lub przewijał cały wynik kursora do pliku tymczasowego i zamknąć połączenie DB.

Ważne zastrzeżenia :

  • wymaga UNIQUE ograniczenia / UNIQUE indeks lub PRIMARY KEY, aby były wiarygodne
  • różne współbieżne zachowanie modyfikacji w celu ograniczenia / przesunięcia, patrz powyżej
 26
Author: Craig Ringer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-23 01:39:16

Niech API zaakceptuje offset do rozpoczęcia i liczbę rekordów do powrotu. Jest to rodzaj stronicowania, w którym Klient może określić, ile rekordów należy zwrócić w żądaniu na jednej stronie. API powinno również zwracać całkowitą liczbę rekordów możliwych dla zapytania, aby klient wiedział, ile "stron", lub opcjonalnie może uzyskać, gdy pobrał ostatnie rekordy, gdy liczba rekordów zwróconych jest zerowa lub mniejsza niż liczba rekordów wymaganych. Możesz to kontrolować w swoim Zapytanie PostgresSQL przy użyciu klauzuli OFFSET (od którego rekordu należy rozpocząć pobieranie) i klauzuli LIMIT (liczba rekordów do zwrócenia) w instrukcji SELECT.

 1
Author: Kevin Junghans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-30 17:12:53