PostgreSQL:n antipatterns: "kuolleiden" laumojen taistelu

PostgreSQL:n sisäisten mekanismien erityispiirteet sallivat sen olevan joissain tilanteissa erittäin nopea ja toisissa "ei kovin nopea". Tänään keskitymme klassiseen esimerkkiin ristiriidasta sen välillä, miten DBMS toimii ja mitä kehittäjä tekee sillä - UPDATE vs MVCC -periaatteet.

Lyhyt tarina kohteesta hieno artikkeli:

Kun riviä muokataan UPDATE-komennolla, suoritetaan kaksi toimintoa: DELETE ja INSERT. SISÄÄN merkkijonon nykyinen versio xmax on yhtä suuri kuin PÄIVITYKSEN suorittaneen tapahtuman numero. Sitten se luodaan uusi versio sama rivi; sen xmin-arvo on sama kuin edellisen version xmax-arvo.

Jonkin ajan kuluttua tämän tapahtuman päättymisestä, vanha tai uusi versio riippuen COMMIT/ROOLBACK, tunnistetaan "kuollut" (kuollut tuples) ohittaessaan VACUUM taulukon mukaan ja tyhjennetty.

PostgreSQL:n antipatterns: "kuolleiden" laumojen taistelu

Mutta tämä ei tapahdu heti, mutta ongelmat "kuolleiden" kanssa voidaan hankkia hyvin nopeasti - toistuvilla tai ennätysten massapäivitys suuressa pöydässä, ja vähän myöhemmin kohtaat saman tilanteen VACUUM ei voi auttaa.

#1: Tykkään siirtää sitä

Oletetaan, että menetelmäsi työskentelee liiketoimintalogiikassa, ja yhtäkkiä se tajuaa, että X-kenttä olisi tarpeen päivittää jossain tietueessa:

UPDATE tbl SET X = <newX> WHERE pk = $1;

Sitten suorituksen edetessä käy ilmi, että myös Y-kenttä tulisi päivittää:

UPDATE tbl SET Y = <newY> WHERE pk = $1;

... ja sitten myös Z - miksi tuhlata aikaa pikkuasioihin?

UPDATE tbl SET Z = <newZ> WHERE pk = $1;

Kuinka monta versiota tästä tietueesta meillä on nyt tietokannassa? Joo, 4 kpl! Näistä yksi on olennainen, ja kolme on siivottava perässäsi [auto]VACUUMilla.

Älä tee sitä näin! Käyttää päivittää kaikki kentät yhdellä pyynnöllä - melkein aina menetelmän logiikkaa voidaan muuttaa seuraavasti:

UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;

#2: Käyttö ON ERILÄINEN, Luke!

Joten halusit silti päivittää monia, monia tietueita taulukossa (esimerkiksi komentosarjan tai muuntimen käytön aikana). Ja jotain tällaista lentää käsikirjoitukseen:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;

Suunnilleen tämän muotoinen pyyntö tulee melko usein ja lähes aina, ettei tyhjää uutta kenttää täytä, vaan tiedoissa olevia virheitä korjataan. Samalla hän itse olemassa olevien tietojen oikeellisuutta ei oteta lainkaan huomioon - mutta turhaan! Toisin sanoen levy kirjoitetaan uudelleen, vaikka se sisältäisi juuri sen, mitä haluttiin - mutta miksi? Korjataan se:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>;

Monet ihmiset eivät ole tietoisia tällaisen upean operaattorin olemassaolosta, joten tässä on huijauslehti IS DISTINCT FROM ja muut loogiset operaattorit auttamaan:
PostgreSQL:n antipatterns: "kuolleiden" laumojen taistelu
... ja vähän monimutkaisista toiminnoista ROW()-ilmaisut:
PostgreSQL:n antipatterns: "kuolleiden" laumojen taistelu

#3: Tunnistan rakkaani... estämisestä

käynnistetään kaksi identtistä rinnakkaista prosessia, joista jokainen yrittää merkitä merkinnän, että se on käynnissä:

UPDATE tbl SET processing = TRUE WHERE pk = $1;

Vaikka nämä prosessit todella tekevät asioita toisistaan ​​riippumatta, mutta saman tunnuksen sisällä, toinen asiakas "lukitaan" tähän pyyntöön, kunnes ensimmäinen tapahtuma on suoritettu.

Ratkaisu # 1: tehtävä vähennetään edelliseen

Lisätään se taas IS DISTINCT FROM:

UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;

Tässä muodossa toinen pyyntö ei yksinkertaisesti muuta mitään tietokannassa, kaikki on jo niin kuin pitäisi - siksi estoa ei tapahdu. Seuraavaksi käsittelemme tosiasiaa, että tietuetta "ei löydy" käytetystä algoritmista.

Ratkaisu # 2: neuvovat lukot

Iso aihe erilliselle artikkelille, josta voit lukea sovellusmenetelmät ja suositeltavan eston "harava"..

Ratkaisu # 3: tyhmät puhelut

Mutta juuri tämän pitäisi tapahtua sinulle samanaikainen työ samalla levyllä? Vai sotkitko esimerkiksi asiakaspuolen liiketoimintalogiikan kutsumisen algoritmeja? Ja jos sitä ajattelee..?

Lähde: will.com

Lisää kommentti