Heddiw ni fydd unrhyw achosion cymhleth ac algorithmau soffistigedig yn SQL. Bydd popeth yn syml iawn, ar lefel Capten Amlwg - gadewch i ni ei wneud edrych ar y gofrestr digwyddiadau trefnu yn ôl amser.
Hynny yw, mae arwydd yn y gronfa ddata events
, ac mae ganddi faes ts
- yr union amser yr ydym am arddangos y cofnodion hyn mewn modd trefnus:
CREATE TABLE events(
id
serial
PRIMARY KEY
, ts
timestamp
, data
json
);
CREATE INDEX ON events(ts DESC);
Mae’n amlwg na fydd gennym ddwsin o gofnodion yno, felly bydd angen rhyw fath o llywio tudalen.
#0. “Fi yw pogromydd fy mam”
cur.execute("SELECT * FROM events;")
rows = cur.fetchall();
rows.sort(key=lambda row: row.ts, reverse=True);
limit = 26
print(rows[offset:offset+limit]);
Nid yw bron yn jôc - mae'n brin, ond i'w chael yn y gwyllt. Weithiau, ar ôl gweithio gydag ORM, gall fod yn anodd newid i waith “uniongyrchol” gyda SQL.
Ond gadewch i ni symud ymlaen at broblemau mwy cyffredin a llai amlwg.
#1. GWRTHOD
SELECT
...
FROM
events
ORDER BY
ts DESC
LIMIT 26 OFFSET $1; -- 26 - записей на странице, $1 - начало страницы
O ble daeth y rhif 26? Dyma amcangyfrif nifer y cofnodion i lenwi un sgrin. Yn fwy manwl gywir, roedd 25 yn dangos cofnodion, ynghyd ag 1, yn nodi bod o leiaf rhywbeth arall ymhellach yn y sampl a'i fod yn gwneud synnwyr i symud ymlaen.
Wrth gwrs, ni ellir “gwnïo” y gwerth hwn i gorff y cais, ond ei basio trwy baramedr. Ond yn yr achos hwn, ni fydd yr amserlennydd PostgreSQL yn gallu dibynnu ar y wybodaeth y dylai fod nifer gymharol fach o gofnodion - a bydd yn hawdd dewis cynllun aneffeithiol.
Ac er yn y rhyngwyneb cais, mae edrych ar y gofrestrfa yn cael ei weithredu fel newid rhwng “tudalennau” gweledol, nid oes unrhyw un yn sylwi ar unrhyw beth amheus am amser hir. Yn union tan yr eiliad pan, yn y frwydr am gyfleustra, mae UI/UX yn penderfynu ail-wneud y rhyngwyneb i “sgrolio diddiwedd” - hynny yw, mae holl gofnodion y gofrestrfa yn cael eu tynnu mewn un rhestr y gall y defnyddiwr sgrolio i fyny ac i lawr.
Ac felly, yn ystod y profion nesaf, rydych chi'n cael eich dal dyblygu cofnodion yn y gofrestrfa. Pam, oherwydd bod gan y tabl fynegai arferol (ts)
, ar ba un y mae eich ymholiad yn dibynnu?
Yn union oherwydd na wnaethoch chi ystyried hynny ts
nid yw'n allwedd unigryw yn y tabl hwn. Mewn gwirionedd, a nid yw ei werthoedd yn unigryw, fel unrhyw “amser” mewn amodau real – felly, mae’r un cofnod mewn dau ymholiad cyfagos yn “neidio” yn hawdd o dudalen i dudalen oherwydd trefn derfynol wahanol o fewn y fframwaith o ddidoli’r un gwerth allweddol.
Mewn gwirionedd, mae ail broblem wedi'i chuddio yma hefyd, sy'n llawer anoddach i'w sylwi - ni fydd rhai cofnodion yn cael eu dangos o gwbl! Wedi’r cyfan, cymerodd y cofnodion “dyblyg” le rhywun arall. Gellir dod o hyd i esboniad manwl gyda lluniau hardd
Ehangu'r mynegai
Mae datblygwr cyfrwys yn deall bod angen gwneud yr allwedd mynegai yn unigryw, a'r ffordd hawsaf yw ei ehangu gyda maes amlwg unigryw, y mae PK yn berffaith ar ei gyfer:
CREATE UNIQUE INDEX ON events(ts DESC, id DESC);
Ac mae'r cais yn treiglo:
SELECT
...
ORDER BY
ts DESC, id DESC
LIMIT 26 OFFSET $1;
#2. Newid i "Cyrchwyr"
Beth amser yn ddiweddarach, daw DBA atoch ac mae'n “falch” bod eich ceisiadau
SELECT
...
WHERE
(ts, id) < ($1, $2) -- последние полученные на предыдущем шаге значения
ORDER BY
ts DESC, id DESC
LIMIT 26;
Fe wnaethoch chi anadlu ochenaid o ryddhad nes iddo ddod ...
#3. Glanhau mynegeion
Oherwydd un diwrnod darllenodd eich DBA (ts DESC)
.
Ond beth i'w wneud gyda'r broblem gychwynnol o "neidio" cofnodion rhwng tudalennau?.. Ac mae popeth yn syml - mae angen i chi ddewis blociau gyda nifer ansefydlog o gofnodion!
Yn gyffredinol, pwy sy’n ein gwahardd i ddarllen nid “yn union 26”, ond “dim llai na 26”? Er enghraifft, fel bod yn y bloc nesaf mae cofnodion gyda gwahanol ystyron amlwg ts
- yna ni fydd problem gyda “neidio” cofnodion rhwng blociau!
Dyma sut i gyflawni hyn:
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;
Beth sy'n digwydd yma?
- Rydyn ni'n camu 25 o gofnodion “i lawr” ac yn cael y gwerth “ffin”.
ts
. - Os nad oes unrhyw beth yno eisoes, rhowch y gwerth NULL yn ei le
-infinity
. - Rydym yn tynnu'r segment cyfan o werthoedd rhwng y gwerth a dderbyniwyd
ts
a'r paramedr $1 wedi'i basio o'r rhyngwyneb (y gwerth rendrad “olaf” blaenorol). - Os dychwelir bloc gyda llai na 26 o gofnodion, dyma'r un olaf.
Neu'r un llun:
Achos nawr mae gennym ni nid oes gan y sampl unrhyw “ddechrau” penodol, yna nid oes dim yn ein hatal rhag “ehangu” y cais hwn i'r cyfeiriad arall a gweithredu llwytho deinamig o flociau data o'r “pwynt cyfeirio” i'r ddau gyfeiriad - i lawr ac i fyny.
Nodyn:
- Ydym, yn yr achos hwn rydym yn cyrchu'r mynegai ddwywaith, ond mae popeth “yn ôl mynegai yn unig”. Felly, dim ond canlyniad fydd subquery i un Sgan Mynegai yn Unig ychwanegol.
- Mae'n eithaf amlwg mai dim ond pan fydd gennych werthoedd y gellir defnyddio'r dechneg hon
ts
yn gallu croesi trwy hap a damwain yn unig, a nid oes llawer ohonynt. Os mai eich achos nodweddiadol yw “miliwn o gofnodion yn 00:00:00.000”, ni ddylech wneud hyn. Hynny yw, ni ddylech ganiatáu i achos o'r fath ddigwydd. Ond os bydd hyn yn digwydd, defnyddiwch yr opsiwn gyda mynegai estynedig.
Ffynhonnell: hab.com