Namuhla ngeke kube namacala ayinkimbinkimbi nama-algorithms ayinkimbinkimbi ku-SQL. Konke kuzoba lula kakhulu, ezingeni likaCaptain Obvious - ake sikwenze ukubuka ukubhaliswa komcimbi ihlungwe ngesikhathi.
Okusho ukuthi, kukhona uphawu ku-database events
, futhi unensimu ts
- ngaso kanye isikhathi lapho sifuna ukubonisa khona lawa marekhodi ngendlela ehlelekile:
CREATE TABLE events(
id
serial
PRIMARY KEY
, ts
timestamp
, data
json
);
CREATE INDEX ON events(ts DESC);
Kuyacaca ukuthi ngeke sibe namarekhodi ayishumi nambili lapho, ngakho-ke sizodinga uhlobo oluthile ukuzulazula kwekhasi.
#0. "Ngingumbulali kamama wami"
cur.execute("SELECT * FROM events;")
rows = cur.fetchall();
rows.sort(key=lambda row: row.ts, reverse=True);
limit = 26
print(rows[offset:offset+limit]);
Cishe akulona ihlaya - akuvamile, kodwa kutholakala endle. Kwesinye isikhathi, ngemuva kokusebenza ne-ORM, kungaba nzima ukushintshela emsebenzini "oqondile" nge-SQL.
Kodwa ake siqhubekele ezinkingeni ezivamile nezingacacile kangako.
#1. OFFSET
SELECT
...
FROM
events
ORDER BY
ts DESC
LIMIT 26 OFFSET $1; -- 26 - записей на странице, $1 - начало страницы
Inombolo 26 yavelaphi? Lena inombolo elinganisiwe yokufakiwe ukuze kugcwalise isikrini esisodwa. Ngokunembayo, amarekhodi abonisiwe angama-25, kanye no-1, okubonisa ukuthi kukhona okunye okunye okwengeziwe kusampula futhi kunengqondo ukuqhubeka.
Yiqiniso, leli nani alikwazi "ukuthungwa" emzimbeni wesicelo, kodwa lidlule kupharamitha. Kodwa kulokhu, umhleli we-PostgreSQL ngeke akwazi ukuthembela olwazini lokuthi kufanele kube namarekhodi ambalwa uma kuqhathaniswa - futhi uzokhetha kalula uhlelo olungasebenzi.
Futhi ngenkathi ukwisixhumi esibonakalayo sohlelo lokusebenza, ukubuka ukubhalisa kusetshenziswa njengokushintsha phakathi “kwamakhasi” abonakalayo, akekho oqaphela noma yini esolisayo isikhathi eside. Impela kuze kube isikhathi lapho, emzabalazweni wokwenza lula, i-UI/UX inquma ukwenza kabusha isixhumi esibonakalayo ukuze “siskrole ngokungapheli” - okungukuthi, konke okufakiwe kokubhalisa zidwetshwe ohlwini olulodwa umsebenzisi angakwazi ukuskrola phezulu naphansi.
Ngakho-ke, phakathi nokuhlolwa okulandelayo, uyabanjwa ukuphindwaphindwa kwamarekhodi endaweni yokubhalisa. Kungani, ngoba ithebula linenkomba evamile (ts)
, umbuzo wakho uncike kuphi?
Impela ngoba awuzange ukucabange lokho ts
akuyona ukhiye oyingqayizivele kuleli tafula. Eqinisweni, futhi amanani ayo awahlukile, njenganoma yisiphi “isikhathi” ezimweni zangempela - ngakho-ke, irekhodi elifanayo emibuzweni emibili eseduze “leqa” kalula lisuka ekhasini liye ekhasini ngenxa yokuhleleka kokugcina okuhlukile ngaphakathi kohlaka lokuhlunga inani lokhiye elifanayo.
Eqinisweni, kuphinde kube nenkinga yesibili efihliwe lapha, okunzima kakhulu ukuyibona - okunye okufakiwe ngeke kuboniswe kube bonke! Phela, amarekhodi "ayimpinda" athathe indawo yomunye umuntu. Incazelo enemininingwane enezithombe ezinhle ingatholakala
Ukunweba inkomba
Unjiniyela onobuqili uyaqonda ukuthi ukhiye wenkomba udinga ukwenziwa uhluke, futhi indlela elula ukuwukhulisa ngenkambu ehlukile esobala, i-PK eyilungele:
CREATE UNIQUE INDEX ON events(ts DESC, id DESC);
Futhi isicelo siyashintsha:
SELECT
...
ORDER BY
ts DESC, id DESC
LIMIT 26 OFFSET $1;
#2. Shintshela kokuthi “izikhombisi”
Ngemva kwesikhathi esithile, i-DBA iza kuwe futhi “iyajabula” ukuthi izicelo zakho
SELECT
...
WHERE
(ts, id) < ($1, $2) -- последние полученные на предыдущем шаге значения
ORDER BY
ts DESC, id DESC
LIMIT 26;
Waphefumulela phezulu waze wafika...
#3. Ukuhlanza izinkomba
Ngoba ngolunye usuku i-DBA yakho yafunda (ts DESC)
.
Kodwa yini okufanele uyenze ngenkinga yokuqala "yokweqa" amarekhodi phakathi kwamakhasi? .. Futhi konke kulula - udinga ukukhetha amabhulokhi ngenombolo engagxiliwe yamarekhodi!
Ngokuvamile, ubani osenqabela ukuthi singafundi “ngqo 26”, kodwa “hhayi ngaphansi kuka-26”? Ngokwesibonelo, ukuze block elilandelayo kukhona amarekhodi anezincazelo ezahlukene ngokusobala ts
- khona-ke ngeke kube nenkinga ngamarekhodi "okweqa" phakathi kwamabhulokhi!
Nansi indlela yokufeza lokhu:
SELECT
...
WHERE
ts < $1 AND
ts >= coalesce((
SELECT
ts
FROM
events
WHERE
ts < $1
ORDER BY
ts DESC
LIMIT 1 OFFSET 25
), '-infinity')
ORDER BY
ts DESC;
Kwenzakalani lapha?
- Sinyathela amarekhodi angama-25 "phansi" futhi sithole inani "lomngcele".
ts
. - Uma kungekho lutho kakade, shintsha inani le-NULL ngokuthi
-infinity
. - Sikhipha yonke ingxenye yamanani phakathi kwevelu etholiwe
ts
kanye nepharamitha engu-$1 edluliselwe kusixhumi esibonakalayo (inani elinikeziwe “lokugcina” langaphambilini). - Uma ibhulokhi ibuyiswa inamarekhodi angaphansi kuka-26, ingeyokugcina.
Noma isithombe esifanayo:
Ngoba manje sesinabo isampula alinaso "isiqalo" esiqondile, lapho-ke akukho okusivimbelayo “ekwandiseni” lesi sicelo kwelinye icala futhi sisebenzise ukulayishwa okuguquguqukayo kwamabhulokhi edatha ukusuka “kuphoyinti lereferensi” kuzo zombili izinkomba - kokubili phansi naphezulu.
Qaphela
- Yebo, kulesi simo sifinyelela inkomba kabili, kodwa yonke into "i-purely by index". Ngakho-ke, i-subquery izophumela kuphela kokukodwa okwengeziwe Ukuskena Kwenkomba Kuphela.
- Kusobala ukuthi le ndlela ingasetshenziswa kuphela uma unamanani
ts
angawela ngenhlanhla kuphela, futhi azikho eziningi zazo. Uma icala lakho elijwayelekile “lingamarekhodi ayisigidi ngo-00:00:00.000”, akufanele ukwenze lokhu. Ngisho ukuthi, akufanele uvumele icala elinjalo ukuba lenzeke. Kodwa uma lokhu kwenzeka, sebenzisa inketho ngenkomba enwetshiwe.
Source: www.habr.com