actualizare: 2014-11-19: unii oameni m-au întrebat cât de mult ajută crearea unui index pe event(channel,id). Răspuns: nu prea mult.

în timpul punerii în aplicare a IRCBrowse am descoperit că Postgres built-in offset nu este foarte rapid.

iată caracteristicile datelor mele:

și dimensiunea:

ircbrowse=> select count(*) from event; count---------- 28673917

Canalul 1 este cel mai mare:

ircbrowse=> select count(*) from event where channel = 1; count---------- 19340467

când lucrați cu date la această scară (mari, dar nu „date mari”), PostgreSQL o gestionează frumos. Dar viteza OFFSET / LIMIT nu este mare:

cred că această scanare index este pur și simplu prea scump. Observați că eu sunt comanda de id-ul care are un indice btree unic pe ea. Verificați viteza:

ircbrowse=> select * from event where channel = 1 order by id offset 1000 limit 30;Time: 0.721 msircbrowse=> select * from event where channel = 1 order by id offset 500000 limit 30;Time: 191.926 ms

s-ar putea să credeți că mai puțin de o secundă pentru a trece prin 500.000 de rânduri dintr-o masă de 28 de milioane de rânduri este destul de bună, dar cred că e de rahat. Este, de asemenea, înșelătoare. Să-l crească la 1.000.000 de rânduri (de 19,000,00):

ircbrowse=> select * from event where channel = 1 order by id offset 1000000 limit 30;Time: 35022.464 ms

acest lucru se înrăutățește și mai rău! Este, probabil, liniar în performanțele sale slabe.

cu toate acestea, există o soluție. Utilizați un tabel index. Un tabel separat care conține chei străine care indică acest tabel:

acum Puteți avea un index de paginare pentru canal 1:

ircbrowse=> select * from event_order_index where idx = 1000 limit 1; id | origin | idx----+--------+------ 1 | 1 | 1000

(am folosit idx = 1000 pentru canalul 1, 2000 pentru canalul 2 etc. așa că aș avea spațiu pentru alți indici numerici pentru același canal.)

acum Puteți face o interogare foarte eficientă pentru aceleași date ca mai sus:

acesta este un timp mai mult sau mai puțin constant.

și puteți vedea acest lucru în acțiune pe site. Durează aproximativ 30ms pentru a încărca și a face pagina dacă rulez acest lucru pe server:

$ time curl 'http://ircbrowse.net/browse/haskell?events_page=234'real0m0.031suser0m0.000ssys 0m0.004s

desigur, trimiterea unei solicitări în browserul dvs. va dura mai mult din cauza conexiunii aeriene și a activelor, dar, în general, Obiectivul a fost ca aceasta să fie foarte rapidă. Vechiul ircbrowse.com (de către un alt individ, care cu amabilitate Lasa-Ma Sa Am numele) a fost foarte lent, într-adevăr. Veți vedea pagina încărcând datele incremental din Baza de date.

anyhoo, a crezut că a fost o optimizare decentă, practică PostgreSQL specifică în ceea ce privește paginarea. Sper că a meritat să scriu.