2015. aasta Alexey LesovskĂ”i ettekande "SĂŒgav kaevamine PostgreSQL sisestatistika" tĂ”lgendus
Ettekande autori teadanne: Tahan mĂ€rkida, et see ettekande kuupĂ€ev on novembris 2015 â on möödunud ĂŒle 4 aasta ja palju on juhtunud. Ettekandes kĂ€sitletud versioon 9.4 ei ole enam toetatud. Viimase 4 aasta jooksul on ilmunud 5 uut versiooni, kus on palju uuendusi, parandusi ja muudatusi, mis puudutavad statistikat, ning osa materjalist on aja jooksul vananenud ja ei ole enam asjakohane. Ălevaatamisel pĂŒĂŒdsin mĂ€rkida neid kohti, et mitte eksitada sind, lugeja. Ma ei hakanud neid kohti ĂŒmber kirjutama, sest neid on vĂ€ga palju ja see tooks lĂ”puks vĂ€lja hoopis teistsuguse ettekande.
PostgreSQL andmebaas on ulatuslik sĂŒsteem, mille erinevad alamsĂŒsteemid mĂ”jutavad otse andmebaasi jĂ”udlust. Töö kĂ€igus kogutakse statistikat ja teavet komponentide toimimise kohta, mis vĂ”imaldab hinnata PostgreSQL efektiivsust ja vĂ”tta meetmeid jĂ”udluse parandamiseks. Kuid, selle teabe hulk on suur ja see esitatakse ĂŒsna lihtsustatud vormis. Selle teabe töötlemine ja tĂ”lgendamine on tihti keeruline ĂŒlesanne, ning "loomaaed" tööriistu ja utiliite vĂ”ib isegi kogenud DBA jaoks segadusse ajada.


Tere pĂ€evast! Minu nimi on Aleksei. Nagu Ilya ĂŒtles, rÀÀgin ma PostgreSQL statistika kohta.

PostgreSQL aktiivsuse statistika. PostgreSQL-l on kaks statistikat. Aktiivsuse statistika, millest juttu tuleb. Ja planeerija statistika andmete jaotuse kohta. RÀÀgin just PostgreSQL aktiivsuse statistikast, mis vÔimaldab meil teha jÀreldusi jÔudluse kohta ja selle parandamise vÔimalustest.
RÀÀgin, kuidas tÔhusalt kasutada statistikat erinevate probleemide lahendamiseks, mis teil on vÔi vÔivad tekkida.

Mida ma ettekandes ei kÀsitle? Ettekandes ei puuduta ma planeerija statistikat, kuna see on eraldi teema eraldi ettekandes, kuidas andmeid andmebaasis hoitakse ja kuidas pÀringute planeerija saab aru nende andmete kvaliteedist ja kvantitatiivsest iseloomust.
Ja ei tule ĂŒlevaateid tööriistadest, ma ei hakka ĂŒhte toodet teisega vĂ”rreldes. Reklaami ei tule. JĂ€tame selle kĂ”rvale.

Ma tahan teile nÀidata, et statistika kasutamine on kasulik. See on vajalik. Selle kasutamine ei ole hirmus. Meie jaoks on vajalik ainult tavaline SQL ja pÔhiteadmised SQL-i kohta.
Ja rÀÀgime, millist statistikat valida probleemide lahendamiseks.

Kui vaatame PostgreSQL-i ja kĂ€ivitame operatsioonisĂŒsteemis protsesside vaatamiseks kĂ€su, siis nĂ€eme "mustas kastis". Me nĂ€eme mingeid protsesse, mis midagi teevad, ja me saame nende nimede jĂ€rgi enam-vĂ€hem aru, mida nad seal teevad, millega nad tegelevad. Kuid tegelikult on see must kast, me ei nĂ€e sisse.
Saame vaadata protsessori koormust top, saame vaadata mĂ€lukasutust mĂ”ne sĂŒsteemiteenuse abil, kuid PostgreSQL sisse vaadata me ei saa. Selleks on meil vaja teisi tööriistu.

Ja edasi rÀÀkides rÀÀgin, kuhu aeg lÀheb. Kui me kujutame PostgreSQL'i sellise skeemina, siis saame vastata, kuhu aeg kulub. See on kaks asja: kliendi rakenduste pÀringute töötlemine ja taustategevused, mida PostgreSQL tÀidab oma töövÔime hoidmiseks.
Kui me vaatame vasakult ĂŒlemisest nurgast, saame jĂ€lgida, kuidas klientide pĂ€ringud töödeldakse. PĂ€ring tuleb rakendusest ja edasise töö jaoks avatakse kliendi sessioon. PĂ€ring edastatakse planeerijale. Planeerija koostab pĂ€ringu plaani. Saadetakse see tĂ€itmiseks edasi. Toimub mingisugune plokkide kaupa andmete sisestamine ja vĂ€ljund, mis on seotud tabelite ja indeksitega. Vajalikud andmed loetakse ketastest mĂ€llu spetsiaalsesse ala "shared buffers". PĂ€ringu tulemused, kui need on uuendused vĂ”i kustutamised, registreeritakse tehingute ajaloos WAL. Teatud statistiline teave jĂ”uab logisse vĂ”i statistika kogumise kollektorisse. Ja pĂ€ringu tulemus antakse kinnituseks tagasi kliendile. PĂ€rast seda saab klient kĂ”ik uuesti alustada uue pĂ€ringuga.
Mis toimub meie taustategevuste ja taustaprotsessidega? Meil on mitu protsessi, mis tagavad sĂŒsteemi töökindluse ja hoiavad andmebaasi normaalses tööreĆŸiimis. Need protsessid kajastuvad ka aruandes: autovacuum, checkpointer, protsessid, mis on seotud replikeerimisega, taustakirjutaja. KĂ€sitlen igaĂŒht neist oma ettekande kĂ€igus.

Millised probleemid on statistika osas?
- Teavet on palju. PostgreSQL 9.4 pakub 109 meetrit statistikaandmete vaatamiseks. Siiski, kui andmebaasis on palju tabeleid, skeeme ja baase, tuleb kÔik need meetrid korrutada vastava tabelite ja baaside arvuga. See tÀhendab, et teabe hulk kasvab veelgi. Ja selle sees on vÀga lihtne Àra uppuda.
- JĂ€rgmine probleem on see, et statistika esitatakse loendureina. Kui me vaatame seda statistikat, nĂ€eme pidevalt kasvavaid loendureid. Ja kui ajavahemik alates statistika lĂ€htestamisest on olnud vĂ€ga pikk, nĂ€eme miljardilisi vÀÀrtusi. Need ei ĂŒtle meile midagi.
- Ajaloo puudumine. Kui teil on toimunud mingi tÔrge, nÀiteks midagi kukkus 15-30 minutit tagasi, siis ei ole vÔimalik kasutada statistikat, et nÀha, mis toimus 15-30 minutit tagasi. See on probleem.
- PostgreSQLi sisseehitatud tööriistade puudumine on probleem. Tuuma arendajad ei paku mingit tööriista. Neil pole midagi sellist. Nad lihtsalt annavad statistika andmebaasi. Kasutage seda, esitage sellele pÀring, tehke, mida soovite.
- Kuna PostgreSQL-is ei ole sisseehitatud tööriista, on see pĂ”hjuseks teisele probleemile. Paljusid kolmanda osapoole tööriistu. Igal ettevĂ”ttel, kellel on rohkem-vĂ€hem oskuslikud töötajad, on oma programm. Ja lĂ”puks on kogukonnas palju tööriistu, mida saab statistika töötlemiseks kasutada. Ăhes tööriistades on ĂŒhed vĂ”imalused, teistes aga teised, vĂ”i on pakutud uusi funktsioone. Tekkib olukord, kus on vaja kasutada kahte, kolme vĂ”i nelja tööriista, mis kattuvad omavahel ja pakuvad erinevaid funktsioone. See on vĂ€ga ebameeldiv.

Mida sellest jÀreldada? On oluline osata statistikat otse vÔtta, et sÔltuda mitte programmide töötlusest, vÔi kuidagi ise neid programme parandada: lisada funktsioone, et saada enda kasu.
Ja on vajalikud pÔhilised SQL-teadmised. Et saada andmeid statistika kohta, tuleb koostada SQL pÀringud, st peate teadma, kuidas koostada select ja join.

Statistika pakub meile mitmeid asju. Need saab jagada kategooriatesse.
- Esimese kategooria alla kuuluvad sĂŒndmused, mis esinevad andmebaasis. See on, kui andmebaasi toimub mingi sĂŒndmus: pĂ€ring, tabeli juurde pÀÀsemine, automaatne tĂŒhjendamine, kommid, need kĂ”ik on sĂŒndmused. Vastavad sellele sĂŒndmusele loendurid suurenevad. Ja me saame neid sĂŒndmusi jĂ€lgida.
- Teine kategooria on objektide omadused, nagu tabelid ja andmebaasid. Neil on omadused. See on tabelite suurus. Saame jĂ€lgida tabelite suuruse kasvu, indeksite suurenemist. Saame vaadata muutusi dĂŒnaamikas.
- Ja kolmas kategooria on sĂŒndmusele kulutatud aeg. PĂ€ring on sĂŒndmus. Sellel on oma konkreetne kestuse mÔÔt. Siin see kĂ€ivitus, seal see lĂ”ppes. Saame seda jĂ€lgida. Samuti jĂ€lgitakse diskilt lugemise vĂ”i kirjutamise aega. Sellised asjad jĂ€lgitakse samuti.

Statistika allikad on esitatud jÀrgmiselt:
- Jagatud mĂ€lus (shared buffers) on segment, kus hoitakse statistilisi andmeid, seal on ka need samad loendurid, mis pidevalt suurenevad, kui toimuvad mingid sĂŒndmused vĂ”i tekivad teatud hetked andmebaasi töös.
- Need performance measurements beyond what your users and admins can access? PostgreSQL offers a suite of low-level metrics through SQL functions. By performing a select query using these functions, you can obtain specific metrics.
- However, working with these functions directly can be cumbersome. This is where views (VIEWs) come into play. They serve as virtual tables that provide statistics for specific subsystems or sets of events within the database.
- These built-in views (VIEWs) are the primary means for users to engage with statistical data. They are readily available by default with no additional setup required, allowing you to access and extract information immediately. Additionally, there are official contrib modules. You can install the postgresql-contrib package (for instance, postgresql94-contrib), load the necessary module in your configuration, set its parameters, restart PostgreSQL, and start using it. (Note. Depending on the distribution, in recent versions, the contrib package is included as part of the main package.).
- Ja on olemas mitteametlikud contrib. Need ei kuulu PostgreSQL standardsetesse pakettidesse. Need tuleb kas koos kompileerida vÔi installida raamatukoguna. Valikud vÔivad olla vÀga erinevad, sÔltuvalt sellest, mida selle mitteametliku contrib'i arendaja on vÀlja mÔelnud.

Sellel slaidil on esitatud kĂ”ik need vaated (VIEWd) ja osa funktsioone, mis on saadaval PostgreSQL 9.4-s. Nagu nĂ€eme, on neid palju. Ja ĂŒsna lihtne on segadusse minna, kui olete sellega esmakordselt kokku puutunud.

Kuid kui vĂ”tame eelneva pildi Kuidas kulub aeg PostgreSQL-i kasutamisel ja ĂŒhitame selle nimekirjaga, siis saame sellise pildi. Iga vĂ€li (VIEWd) vĂ”i iga funktsioon, mida saame kasutada erinevatel eesmĂ€rkidel, et saada vastavat statistikat, kui meil on PostgreSQL töömas. Ja me saame juba mingit teavet alamhaldussĂŒsteemi töö kohta.

Esimene asi, mida vaatame, on pg_stat_database. Nagu nÀeme, on see vÀli. Seal on vÀga palju teavet. KÔige mitmekesisemat teavet. Ja see annab vÀga vÀÀrtuslikku teadmist selle kohta, mis meie andmebaasis toimub.
Mida kasulikku saame sealt vÔtta? Alustame kÔige lihtsamatest asjadest.

select
sum(blks_hit)*100/sum(blks_hit+blks_read) as hit_ratio
from pg_stat_database;Esiteks, mida saame vaadata, on vahemÀlu hiti protsent. VahemÀlu hiti protsent on kasulik mÔÔdik. See vÔimaldab hinnata, kui palju andmeid vÔetakse vahemÀlust (shared buffers) ja kui palju loetakse kettalt.
Selgelt on nĂ€ha, et mida suurem on meie vahemĂ€lu hiti protsent, seda parem on see.. Me hindame seda mÔÔdikut protsendina. Ja nĂ€iteks, kui meil on vahemĂ€lu hiti protsent ĂŒle 90%, siis on see hea. Kui see langeb alla 90%, siis nĂ€itab see, et meil pole piisavalt mĂ€lu, et hoida kuuma andmete "pead" mĂ€lus. Ja et neid andmeid kasutada, peab PostgreSQL pöörduma ketta poole, mis on aeglasem kui andmete lugemine mĂ€lust. Siis tuleks juba mĂ”elda mĂ€lu suurendamisele: kas suurendada shared buffersi vĂ”i lisada rohkem fĂŒĂŒsilist mĂ€lu (RAM).

select
datname,
(xact_commit*100)/(xact_commit+xact_rollback) as c_ratio,
deadlocks, conflicts,
temp_file, pg_size_pretty(temp_bytes) as temp_size
from pg_stat_database;Mida veel saame sellest esitamisest vÔtta? Saame vaadata andmebaasis toimuvaid anomaaliaid. Mida siin nÀidatakse? Siin on commits, rollbacks, ajutiste failide loomine ja nende maht, deadlocks ja konfliktid.
Saame kasutada seda pĂ€ringut. See SQL on ĂŒsna lihtne. Ja saame neid andmeid enda juures vaadata.

Siin on kohe piirvÀÀrtused. Me vaatame commits ja rollbacks suhet. Commits on eduka tehingu kinnitamine. Rollbacks on tagasivÔtmine, st tehing tegi mingit tööd, koormas andmebaasi, tegi arvutusi, kuid siis toimus tÔrge ja tehingu tulemused kÔrvaldatakse. St. korrutusi, mis pidevalt suurenevad, on halb. Ja peaks neid vÀltima ning koodi parandama, et sellist ei juhtuks.
Konfliktid (conflicts) on seotud replikatsiooniga. Ja neid tuleks samuti vĂ€ltida. Kui teil on mĂ”ni pĂ€ring, mis töötab replikal ja tekivad konfliktid, tuleb need konfliktid lahendada, vaadata, mis toimub. Ăksikasjad leiab logidest. Ja tuleb kĂ”rvaldada konfliktolukordi, et rakenduse pĂ€ringud töötaksid ilma vigadeta.
Deadlockid â see on samuti halb olukord. Kui pĂ€ringud konkureerivad ressursside pĂ€rast, pöördub ĂŒks pĂ€ring ĂŒhe ressursi poole ja vĂ”tab selle blokeeringu, teine pĂ€ring pöördub teise ressursi poole ja vĂ”tab samuti blokeeringu, ning seejĂ€rel pöörduvad mĂ”lemad pĂ€ringud ĂŒksteise ressursside poole ja takerdusid ootama, kuni naaber blokeeringu vabastab. See on samuti probleemne olukord. Neid tuleb lahendada rakenduste ĂŒmberehitamise ja ressurssidele juurdepÀÀsu serialiseerimise tasemel. Ja kui te nĂ€ete, et teie deadlockid suurenevad pidevalt, tuleb uurida ĂŒksikasju logidest, analĂŒĂŒsida tekkinud olukordi ja otsida, mis on probleem.
Ajutised failid (temp_files) â see on samuti halb. Kui kasutaja pĂ€ringul ei ole mĂ€lu, et paigutada operatiivseid ajutisi andmeid, loob ta faili kettale. Ja kĂ”ik operatsioonid, mida ta saaks teostada ajutises mĂ€lupuhvrisse, hakkab ta teostama juba kettal. See on aeglane. See suurendab pĂ€ringu tĂ€itmise aega. Ja klient, kes saatis pĂ€ringu PostgreSQL-ile, saab vastuse veidi hiljem. Kui kĂ”ik need operatsioonid teostatakse mĂ€lus, vastab Postgres palju kiiremini ja klient peab vĂ€hem ootama.

Pg_stat_bgwriter â see vaade kirjeldab kahe PostgreSQL taustasĂŒsteemi tööd: see kontrollpunkt ja taustakirjutaja.

Alustame kontrollpunktidest, st. kontrollpunktid. Mis on kontrollpunktid? Kontrollpunkt on positsioon tehingute logis, mis teatab, et kĂ”ik andmete muudatused, mis on logis registreeritud, on edukalt sĂŒnkroniseeritud andmetega kettal. Protsess vĂ”ib sĂ”ltuvalt töökoormusest ja seadistustest olla pikk ning see seisneb suurel mÀÀral mÀÀrdunud lehtede sĂŒnkroniseerimises jagatud puhvrites kettal olevate andmefailidega. Miks on see vajalik? Kui PostgreSQL pöördus pidevalt kettale ja vĂ”ttis sealt andmeid ning salvestaks andmeid igal korral, kui sealt andmeid vĂ”etakse, oleks see aeglane. SeetĂ”ttu on PostgreSQL-l mĂ€lu segment, mille suurus sĂ”ltub konfiguratsioonis olevatest parameetritest. Postgres salvestab sellesse mĂ€lu operatiivsed andmed hilisemaks töötlemiseks vĂ”i nende esitlemiseks pĂ€ringute jĂ€rgi. Andmete muutmise pĂ€ringute puhul toimub nende muutmine. Ja me saame kaks versiooni andmetest. Ăks on meil mĂ€lus, teine kettal. Ja perioodiliselt on vajalik need andmed sĂŒnkroniseerida. Me peame mĂ€lus muudetud andmed sĂŒnkroniseerima kettale. Selleks on vajalikud kontrollpunktid.
Checkpoint lĂ€bib jagatud puhverid, mĂ€rgib rĂ€paste lehtedena, et need on vajalikud kontrollpunktiks. Siis kĂ€ivitab see teise lĂ€bimise jagatud puhverites. Ja lehed, mis on mĂ€rgitud kontrollpunktiks, sĂŒnkroniseeritakse juba. Niimoodi toimub andmete sĂŒnkroniseerimine ketas.
On kaks tĂŒĂŒpi kontrollpunkte. Ăks kontrollpunkt toimub ajavahemiku jĂ€rgi. See kontrollpunkt on kasulik ja hea â checkpoint_timed. Ja on nĂ”udmisi alusel tehtavad kontrollpunktid â checkpoint required. Selline kontrollpunkt toimub, kui meil on vĂ€ga suur andmete kirjutamine. Oleme kirjutanud vĂ€ga palju tehingute logisid. Ja PostgreSQL peab seda kĂ”ike vĂ”imalikult kiiresti sĂŒnkroniseerima, et teha kontrollpunkt ja edasi elada.
Ja kui vaatasite statistikat pg_stat_bgwriter ja nĂ€gite, et teil on checkpoint_req palju rohkem kui checkpoint_timed, siis see on halb. Miks halb? See tĂ€hendab, et PostgreSQL on pidevas stressis, kui tal on vaja andmeid kettale kirjutada. Checkpoint on vĂ€ljumise aeg vĂ€hem stressirohke ja toimub vastavalt sisemisele ajakavale ning on ajaliselt jaotatud. PostgreSQL-il on vĂ”imalus teha töötamise pausid, et mitte koormata kettasĂŒsteemi. See on PostgreSQL jaoks kasulik. Samuti ei puutu tĂ”rgeteta toimuvad pĂ€ringud stressi, kui kettasĂŒsteem on hĂ”ivatud.
Ja checkpointi reguleerimiseks on kolm parameetrit:
checkpoint_segments.checkpoint_timeout.checkpoint_completion_target.
Need vÔimaldavad reguleerida kontrollpunktide tööd. Kuid ma ei jÀÀ nende juurde. Nende mÔju on juba eraldi teema.
TĂ€htis: Arutletav etapp 9.4 ei ole enam asjakohane. Kaasaegsetes PostgreSQL versioonides on parameeter checkpoint_segments asendatud parameetritega min_wal_size ja max_wal_size.

JĂ€rgmine alamvĂ”rk on taustakirjutaja â taustakirjutaja. Mida ta teeb? Ta töötab pidevalt lĂ”pmatus tsĂŒklis. Skaneerib lehti ĂŒhiskasutatavatest puhkudest ning lehti, mis on mÀÀrdunud, mille ta leiab, kirjutab kettale tagasi. Nii aitab ta checkpointer'il vĂ€hendada töökoormust kontrollpunktide tĂ€itmise protsessis.
Mis see veel on kasulik? See tagab vajaduse puhaste lehtede jĂ€rele jagatud puhverdes, kui need peaksid Ă€kki olema vajalikud (suurtes kogustes ja kohe) andmete salvestamiseks. Oletame, et olukord on tekkinud, kus puhtaid lehti on vaja pĂ€ringu tĂ€itmiseks ja need on juba jagatud puhvris. Postgres tagaosa lihtsalt vĂ”tab need ja kasutab, tal ei ole vaja ise midagi puhastada. Kuid kui selliseid lehti pole, siis backend peatab töötamise ning alustab lehtede otsingut, et need diskile kirjutada ja enda vajaduste jaoks vĂ”tta â see mĂ”jutab negatiivselt hetkel kĂ€imasoleva pĂ€ringu tĂ€itmise aega. Kui nĂ€ete, et teil on parameeter maxwritten_clean suur, tĂ€hendab, et taustakirjutaja ei suuda oma tööd teha ja peab suurendama parameetreid bgwriter_lru_maxpages, et ta suudaks ĂŒhes tsĂŒklis rohkem tööd Ă€ra teha, rohkem lehti puhastada.
Ja teine vĂ€ga kasulik nĂ€itaja on buffers_backend_fsync. Backendid ei tee fsynci, sest see on aeglane. Nad edastavad fsynci kĂ”rgemale IO stackâile checkpointerâile. Checkpointeril on oma jĂ€rjekord, ta töötleb fsynci perioodiliselt ja sĂŒnkroniseerib mĂ€lus lehed failidega diskil. Kui checkpointerâil on suur jĂ€rjekord ja see on tĂ€is, peab backend ise tegema fsync, mis aeglustab backendâi tööd., st. klient saab vastuse hiljem, kui vĂ”iks. Kui nĂ€ete, et see vÀÀrtus on suurem kui null, siis on see juba probleem ja peate pöörama tĂ€helepanu background writerâi seadetele ning hindama ka kettasĂŒsteemi jĂ”udlust.

TĂ€htis: _JĂ€rgmine tekst kirjeldab statistilisi representatsioone, mis on seotud replikatsiooniga. Enamik vaateid ja funktsioonide nimesid on Postgres 10-s ĂŒmber nimetatud. Ămbernimetamine hĂ”lmas xlog jĂ€rgnevaga wal ja asukohta jĂ€rgnevaga lsn funktsioonide/vaadete jne nimedes. Eriline nĂ€ide on funktsioon pg_xlog_location_diff() , mis nimetati ĂŒmber pg_wal_lsn_diff()._
Siin on meil samuti palju asju. Kuid me vajame vaid punkte, mis on seotud locationâiga.

Kui me nÀeme, et kÔik vÀÀrtused on vÔrdsed, on see ideaalne variant ja replikatsioon ei jÀÀ maestro taga.
See kuuekĂŒmnendaline positsioon on positsioon tehingute ajakirjas. See suureneb pidevalt, kui andmebaasis on mingit aktiivsust: lisamised, kustutamised jne.

kui palju xlog on kirjutatud baitides
$ select
pg_xlog_location_diff(pg_current_xlog_location(),'0/00000000');
replicatsiooni viivitus baitides
$ select
client_addr,
pg_xlog_location_diff(pg_current_xlog_location(), replay_location)
fro pg_stat_replication;
replicatsiooni viivitus sekundites
$ select
extract(epoch from now() - pg_last_xact_replay_timestamp());Kui need asjad erinevad, siis tÀhendab see, et on mingisugune viivitus. Viivitus on replika viibimine peamise serveri ees, st andmed erinevad serverite vahel.
On kolm pÔhjust viibimise tekkimiseks:
- See on diskial sĂŒsteem, mis ei suuda kirjutada failide sĂŒnkroniseerimist.
- Need vÔivad olla vÔrguvead vÔi vÔrgu koormus, kui andmed ei jÔua replikasse Ôigel ajal ja ta ei suuda neid taastada.
- Ja protsessor. Protsessor â see on vĂ€ga harv juhtum. Olen sellist nĂ€inud kaks vĂ”i kolm korda, aga see vĂ”ib ka juhtuda.
Ja siin on kolm pĂ€ringut, mis vĂ”imaldavad meil kasutada statistikat. Saame hinnata, kui palju on meie tehingu ĆŸurnalis kirjutatud. On olemas selline funktsioon pg_xlog_location_diff ja saame hinnata replicatsiooni viivitust baitides ja sekundites. Seda jaoks kasutame samuti vÀÀrtust sellest vaatepunktist (VIEWs).
MĂ€rkus: _pg_xlog_locationdiff() funktsiooni asemel saab kasutada lahutamisoperaatorit ja lahutada ĂŒhe asukoha teisest. Mugav.
Aegluse, mis on sekundites, on ĂŒks hetk. Kui meistris ei toimu mingit aktiivsust, oli tehing umbes 15 minutit tagasi ja aktiivsust pole, ja kui me vaatame replikas seda aeglust, siis nĂ€eme 15-minutilist viivitust. Sellest tasub meeles pidada. Ja see vĂ”ib tekitada segadust, kui olete seda viivitust vaadanud.

Pg_stat_all_tables â veel ĂŒks kasulik vaade. See nĂ€itab tabelite statistikat. Kui meie andmebaasis on tabeleid, millega toimub mingisugune aktiivsus, saame seda teavet selle vaate kaudu.

select
relname,
pg_size_pretty(pg_relation_size(relname::regclass)) as size,
seq_scan, seq_tup_read,
seq_scan / seq_tup_read as seq_tup_avg
from pg_stat_user_tables
where seq_tup_read > 0 order by 3,4 desc limit 5;Esimene asi, mida me saame vaadata, on jÀrjestikused skaneerimised tabelis. Number nende lÀbimiste jÀrel ei pruugi olla halb ja ei tÀhenda tingimata, et peame midagi ette vÔtma.
Kuid on ka teine mÔÔdik â seq_tup_read. See on ridade arv, mis tagastatakse jĂ€rjestikulise skaneerimise tulemusena. Kui keskmine number ĂŒletab 1 000, 10 000, 50 000, 100 000, siis on see nĂ€itaja, et vĂ”ib-olla peate kuskil indeksi looma, et juurdepÀÀsud oleksid indeksi kaudu, vĂ”i on vĂ”imalik optimeerida pĂ€ringuid, mis kasutavad selliseid jĂ€rjestikulisi skaneerimisi, et seda vĂ€ltida.
Lihtne nĂ€ide â oletame, et pĂ€ring, millel on suur OFFSET ja LIMIT, on kulukas. NĂ€iteks skaneeritakse 100 000 rida tabelis ja seejĂ€rel vĂ”etakse 50 000 vajalikku rida, samas kui eelnevalt skaneeritud read jĂ€etakse kĂ”rvale. See on samuti halb olukord. Selliseid pĂ€ringuid tuleb optimeerida. Siin on lihtne SQL-pĂ€ring, mille abil saab seda vaadata ja mÔÔdetud numbreid hinnata.

select
relname,
pg_size_pretty(pg_total_relation_size(relname::regclass)) as
full_size,
pg_size_pretty(pg_relation_size(relname::regclass)) as
table_size,
pg_size_pretty(pg_total_relation_size(relname::regclass) -
pg_relation_size(relname::regclass)) as index_size
from pg_stat_user_tables
order by pg_total_relation_size(relname::regclass) desc limit 10;Tabelite suurusi saab samuti saada selle tabeli ja tÀiendavate funktsioonide abil. pg_total_relation_size(), pg_relation_size().
Tegelikult on olemas metakomandid. dt ja di, mida saab kasutada PSQL-is ning samuti vaadata tabelite ja indeksite suurusi.
Kuid funktsioonide kasutamine aitab meil nÀha tabelite suurusi, arvestades indekseid vÔi ilma indekseid arvesse vÔtmata, ning teha juba mingeid hindamisi andmebaasi kasvu pÔhjal, st kuidas see meil kasvab, millise intensiivsusega, ning teha mingeid jÀreldusi suuruste optimeerimise osas.

Kirjutamisaktiivsus. Mis on kirjutamine? Vaatame operatsiooni KUUDA â ridade vĂ€rskendamise operatsiooni tabelis. Sisuliselt on update kaks operatsiooni (vĂ”i isegi enam). See on uue versiooni sisestamine ja vana versiooni mĂ€rgistus aegunuks. Hiljem tuleb autovakuum ja need vanad versioonid eemaldatakse, tĂ€histades selle koha taaskasutamiseks sobivaks.
Lisaks ei tÀhenda update ainult tabeli vÀrskendamist. See hÔlmab ka indeksite vÀrskendamist. Kui teie tabelil on palju indekseid, tuleb update kÀigus kÔik indeksid, kus osaleb vÀrskendatav vÀli, samuti vÀrskendada. Nendes indeksites on samuti vanad versioonid, mida tuleb puhastada.

valige
s.relname,
pg_size_pretty(pg_relation_size(relid)),
coalesce(n_tup_ins,0) + 2 * coalesce(n_tup_upd,0) -
coalesce(n_tup_hot_upd,0) + coalesce(n_tup_del,0) AS total_writes,
(coalesce(n_tup_hot_upd,0)::float * 100 / (case when n_tup_upd > 0
then n_tup_upd else 1 end)::float)::numeric(10,2) AS hot_rate,
(select v[1] FROM regexp_matches(reloptions::text,E'fillfactor=(\d+)') as
r(v) limit 1) AS fillfactor
from pg_stat_all_tables s
join pg_class c ON c.oid=relid
order by total_writes desc limit 50;Ja oma olemuselt on UPDATE â see on keeruline operatsioon. Kuid neid saab kergendada. On kuumad vĂ€rskendused. Need ilmusid PostgreSQL versioonis 8.3. Mis need on? See on kerge vĂ€rskendus, mis ei pĂ”hjusta indeksite ĂŒmberstruktuurimist. See tĂ€hendab, et me vĂ€rskendasime kirjet, kuid muutus ainult lehe kirje (mis kuulub tabelile), ja indeksid suunavad endiselt sellele samale kirjele lehe sees. Siin on pisut huvitav töölogika: kui tuleb vaakum, siis ta need ahelad kuumad uuendab ja kĂ”ik töötab jĂ€tkuvalt ilma indeksite uuendamiseta, ja see toimub vĂ€iksema ressursikulu arvelt.
Ja kui teil on n_tup_hot_upd suure hulga, siis see on vÀga hea. See tÀhendab, et kerged vÀrskendused domineerivad ja see on meie ressursside jaoks odavam ja kÔik on suurepÀrane.

ALTER TABLE table_name SET (fillfactor = 70);Kuidas suurendada kuumade vĂ€rskendustehulka? Me saame kasutada fillfactor. See mÀÀrab reserveeritud vabade kohtade suuruse lehe tĂ€itmisel tabelis INSERT-ide abil. Kui tabelisse sisestatakse andmeid, tĂ€idavad need tĂ€ielikult lehe, jĂ€ttes sellele tĂŒhi koht. SeejĂ€rel eraldatakse uus leht. Andmed tĂ€idetakse uuesti. See on vaikekĂ€itumine, fillfactor = 100%.
Saame seadistada fillfactori 70% peale. See tÀhendab, et kui sisestatakse andmeid, eraldatakse uus leht, kuid tÀidetakse vaid 70% lehe mahust. 30% jÀÀb meile reserviks. Kui tuleb teha uuendus, toimub see tÔenÀoliselt samal lehel, ja uue versiooni rida paigutatakse samasse lehte. Sellega lihtsustatakse tabelite kirjutamist.

select c.relname,
current_setting('autovacuum_vacuum_threshold') as av_base_thresh,
current_setting('autovacuum_vacuum_scale_factor') as av_scale_factor,
(current_setting('autovacuum_vacuum_threshold')::int +
(current_setting('autovacuum_vacuum_scale_factor')::float * c.reltuples))
as av_thresh,
s.n_dead_tup
from pg_stat_user_tables s join pg_class c ON s.relname = c.relname
where s.n_dead_tup > (current_setting('autovacuum_vacuum_threshold')::int
+ (current_setting('autovacuum_vacuum_scale_factor')::float * c.reltuples));Autovakumi jĂ€rjekord. Autovakum on alamsĂŒsteem, mille statistika PostgreSQL-is on vĂ€ga vĂ€ike. Saame tabelites pg_stat_activity vaid nĂ€ha, kui palju meil hetkel autovakume on. Kuid on vĂ€ga keeruline mĂ”ista, kui palju tabeleid on tal jĂ€rjekorras.
MĂ€rkus: _Alates PostgreSQL versioonist 10 on olukord autovakumi jĂ€lgimisel oluliselt paranenud â ilmus vaade pg_stat_progress, mis lihtsustab autovakumi jĂ€lgimise kĂŒsimust oluliselt.
Saame kasutada sellist lihtsustatud pĂ€ringut. Ja saame vaadata, millal peaks vakum olema tehtud. Kuid kuidas ja millal peaks vakum kĂ€ivituma? Need on vananenud stringiversioonid, millest ma varem rÀÀkisin. Uuendus toimus, uus stringiversioon sisestati. Ilmus vananenud stringiversioon. Tabelis pg_stat_user_tables on selline parameeter n_dead_tup. See nĂ€itab "surmatud" stringide arvu. Ja niipea, kui surmatud stringide arv ĂŒletab kindla piiri, tuleb tabelisse autovakum.
Ja kuidas see piir arvutatakse? See on ĂŒsna konkreetne protsentuaalne suhe tabelis olevate stringide koguarvust. On olemas parameeter autovacuum_vacuum_scale_factor. See mÀÀrab protsendi suhte. Oletame, et 10 % + seal on tĂ€iendav baaspiirang 50 rida. Ja mis sellega juhtub? Kui meie surnud ridu on rohkem kui "10 % + 50" kĂ”igist ridadest tabelis, siis paneme tabeli automaatse tĂŒhjendamise (autovacuum) peale.

select c.relname,
current_setting('autovacuum_vacuum_threshold') as av_base_thresh,
current_setting('autovacuum_vacuum_scale_factor') as av_scale_factor,
(current_setting('autovacuum_vacuum_threshold')::int +
(current_setting('autovacuum_vacuum_scale_factor')::float * c.reltuples))
as av_thresh,
s.n_dead_tup
from pg_stat_user_tables s join pg_class c ON s.relname = c.relname
where s.n_dead_tup > (current_setting('autovacuum_vacuum_threshold')::int
+ (current_setting('autovacuum_vacuum_scale_factor')::float * c.reltuples));Kuid siin on ĂŒks moment. Baaspiirangud parameetritel av_base_thresh ja av_scale_factor vĂ”ivad olla mÀÀratud individuaalselt. SeetĂ”ttu ei ole piirang globaalne, vaid individuaalne tabeli jaoks. Seega, et arvutada, peab kasutama nippe ja trikke. Ja kui teid huvitab, siis vĂ”ite vaadata meie kolleegide kogemust Avitos (link slaidil ei ole enam kehtiv ja on tekstis uuendatud).
Nad kirjutasid , mis arvestab neid asju. Seal on kahe lehe pikkune tekst. Kuid see arvutab Ă”igesti ja vĂ”imaldab ĂŒsna efektiivselt hinnata, kus meil tĂŒhjendamine tabelite jaoks on vĂ€ga vajalik, ja kus on seda vĂ€hem.
Mida me sellega teha saame? Kui meil on pikk jĂ€rjekord ja automaatne tĂŒhjendamine ei toimi, saame me suurendada tĂŒhjendamise töötajate arvu vĂ”i lihtsalt teha tĂŒhjendamise agressiivsemaks, et see aktiveeruks varem, töötleks tabelit vĂ€ikeste tĂŒkkidena. Ja seelĂ€bi vĂ€heneb jĂ€rjekord. â Peamine on jĂ€lgida ketaste koormust, kuna vaakum ei ole tasuta, kuigi SSD/NVMe seadmete tulekuga on probleem muutunud vĂ€hem nĂ€htavaks.

Pg_stat_all_indexes â see on statistika indeksite kohta. See on vĂ€ike. Ja me saame selle pĂ”hjal teavet indeksite kasutamise kohta. NĂ€iteks saame mÀÀrata, millised indeksid on meie jaoks ĂŒleliigsed.

Kuidas ma juba mainisin, update â see ei ole ainult tabelite vĂ€rskendamine, vaid ka indeksite vĂ€rskendamine. Seega, kui meil on tabelis palju indekseid, siis tabeli ridade vĂ€rskendamisel tuleb ka indekseeritud vĂ€ljade indeksid vĂ€rskendada, ja kui meil on kasutamata indeksid, mille kohta ei toimu indeksiskaneerimist, siis need on meie jaoks koormaks. Ja neist peab vabanema. Selle jaoks on meil vaja vĂ€lja idx_scan. Vaata lihtsalt indeksiskaneerimiste arvu. Kui indeksitel on null skaneerimist suhteliselt pika statistika sĂ€ilitamise perioodi jooksul (mitte vĂ€hem kui 2-3 nĂ€dalat), siis on tĂ”enĂ€oliselt tegemist halva indekssiga, millest peame vabanema.
MĂ€rkus: Klastri replikatsioonide puhul tĂŒhjade indeksite otsimisel tuleb kontrollida kĂ”iki klastri sĂ”lmi, kuna statistika ei ole globaalne ja kui indeksit ei kasutata peamise serveri peal, vĂ”ib see olla kasutusel koopiates (kui neil on koormus).
Kaks linki:
Need on arenenumad pĂ€ringute nĂ€ited, kuidas leida tĂŒhje indekseid.
Teine link on ĂŒsna huvitav pĂ€ring. Seal on vĂ€ga keeruline loogika. Soovitan tutvuda.

Mis veel indeksite kohta rÔhutada?
TĂŒhjad indeksid on kehvad.
Kasutavad ruumi.
Aeglustavad uuendamise operatsioone.
Liigne töö vahetuks.
Kui me kustutame tĂŒhjad indeksid, teeme andmebaasi ainult paremaks.

JĂ€rgmine vaade on pg_stat_activity. See on tööriista analoog, ps, ainult PostgreSQL-is. Kui pste vaatate 'sĂŒsteemi protsesse, siis pg_stat_activity nĂ€itab teile aktiivsust PostgreSQL-i sees.
Mida kasulikku me sealt saame?

select
count(*)*100/(select current_setting('max_connections')::int)
from pg_stat_activity;Me saame vaadata ĂŒldist aktiivsust, mis andmebaasis toimub. Saame teha uue versiooni. Meil seal kĂ”ik plahvatas, uued ĂŒhendused ei tule, rakenduses viskab vigu.

select
client_addr, usename, datname, count(*)
from pg_stat_activity group by 1,2,3 order by 4 desc;Saame teostada sellise pĂ€ringu ja vaadata ĂŒldist ĂŒhenduste protsenti maksimaalsest piirangust ning vaadata, kes meilt kĂ”ige rohkem ĂŒhendusi kasutab. Ja antud juhul nĂ€eme, et user cron_role avas 508 ĂŒhendust. Ja temaga on midagi juhtunud. Tuleb sellega tegeleda ja uurida. On tĂ€iesti vĂ”imalik, et see on mingi anomaalne ĂŒhenduste arv.

Kui meil on OLTP koormus, peaksid pĂ€ringud toimuma kiiresti, vĂ€ga kiiresti, ja pikad pĂ€ringud ei tohiks olla. Kuid kui pikad pĂ€ringud tekivad, siis lĂŒhiajaliselt ei ole midagi hullu, kuid pikaajalises perspektiivis kahjustavad pikad pĂ€ringud andmebaasi, need suurendavad tabelite bloat-efekti, kui toimub tabelite fragmenteerimine. Bloatâist ja pikkadest pĂ€ringutest tuleb vabaneda.

valige
client_addr, usename, datname,
clock_timestamp() - xact_start as xact_age,
clock_timestamp() - query_start as query_age,
query
from pg_stat_activity order by xact_start, query_start;Pange tÀhele: selle pÀringuga saame kindlaks teha pikaajalised pÀringud ja tehingud. Kasutame funktsiooni clock_timestamp() tööaega mÀÀrata. Pikaajalised pÀringud, mille oleme leidnud, saame neid meelde jÀtta, kÀivitada explain, vaadata plaane ja optimeerida neid. Praegused pikad pÀringud me peatame ja elame edasi.

select * from pg_stat_activity where state in
('idle in transaction', 'idle in transaction (aborted)';Halvad tehingud â need on tehingud seisundis idle in transaction ja idle in transaction (aborted).
Mis see tĂ€hendab? Tehingud vĂ”ivad olla mitmesugustes seisundites. Ja nad vĂ”ivad igal ajahetkel omada ĂŒht neist seisunditest. Seisundite mÀÀramiseks on vĂ€li state selles esitusvormis. Ja kasutame seda jaotuse seisundi mÀÀramiseks.

select * from pg_stat_activity where state in
('idle in transaction', 'idle in transaction (aborted)';Ja nagu ma juba varem ĂŒtlesin, need kaks seisundit idle in transaction ja idle in transaction (aborted) â see on halb. Mis see on? See tĂ€hendab, et rakendus avas tehingu, tegi mĂ”ned toimingud ja lĂ€ks siis omi asju ajama. Tehing jĂ€i avatuks. See jÀÀb rippuma, seal ei toimu mitte midagi, see vĂ”tab ĂŒhenduse, blokeerib muudetud ridu ja vĂ”ib potentsiaalselt suurendada ka teiste tabelite bloat'i, kuna Postgres'i tehingu mootori arhitektuur selline on. Sellised tehingud tuleks samuti lĂ”petada, kuna need on ehk kahjulikud igas olukorras.
Kui teil nÀete, et neid on teie andmebaasis rohkem kui 5-10-20, siis on juba pÔhjust muretseda ja midagi ette vÔtta.
Siin kasutame me ka ajakalkuleerimisel clock_timestamp(). LÔpetame tehingud, optimeerime rakenduse.

Kuidas ma juba varem ĂŒtlesin, lukud â see on siis, kui kaks vĂ”i rohkem tehingut vĂ”itlevad ĂŒhe vĂ”i grupi ressursside pĂ€rast. Selleks on meil vĂ€li waiting boolean vÀÀrtusega true vĂ”i false.
True â see tĂ€hendab, et protsess ootab, vaja on midagi ette vĂ”tta. Kui protsess on ootel, siis tĂ€hendab see, et ka klient, kes algatas selle protsessi, ootab. Klient brauseris istub ka ja ootab.
TÀhtis: _Alates Postgres 9.6 versioonist vÀli waiting kaks rohkem informatiivset vÀlja on asendatud wait_event_type ja wait_event._

Mis teha? Kui te nÀete true pikka aega, siis tÀhendab see, et sellistest pÀringutest tuleb vabaneda. Me lihtsalt tappa sellised tehingud. Arendajatele kirjutame, et nad peavad kuidagi optimeerima, et ressursi jÀrele ei toimuks vÔidujooksu. Ja siis saavad arendajad rakendust optimeerida, et seda ei juhtuks.
Ja viimane, kui ka mitte fataalne juhtum â see on deadlockide teke. Kaks tehingut vĂ€rskendavad kahte ressurssi, seejĂ€rel pöörduvad nad uuesti vastassuunaliste ressursside poole. PostgreSQL tapab sel juhul tehingu, et teine saaks jĂ€tkata tööd. See on ummikus olukord ja see ei lahenda ennast iseseisvalt. SeetĂ”ttu peab PostgreSQL vĂ”tma ÀÀrmuslikke meetmeid.

Ja siin on kaks pÀringut, mis vÔimaldavad jÀlgida lukke. Me kasutame vaadet pg_locks, mis vÔimaldab jÀlgida raskemaid lukke.
Ja esimene link â see on pĂ€ringu tekst. See on ĂŒsna pikk.
Ja teine link â see on artikkel lukustuste kohta. Seda on kasulik lugeda, see on vĂ€ga huvitav.
Nii et mida me nĂ€eme? Me nĂ€eme kahte pĂ€ringut. Tehing koos ALTER TABLE â see on blokeeriv tehing. See kĂ€ivitati, kuid ei lĂ”petatud ning rakendus, mis selle tehingu alustas, tegeleb kuskil muude asjadega. Ja teine pĂ€ring â update. See ootab, kuni alter table lĂ”peb, et jĂ€tkata oma tööd.
Nii me saame vÀlja selgitada, kes kedagi lukustas, hoiab ja saame sellega edasi tegeleda.

JĂ€rgmine moodul â see on pg_stat_statements. Nagu ma juba ĂŒtlesin, see moodul. Selle kasutamiseks tuleb laadida selle raamatukogu konfiguratsioonis, taaskĂ€ivitada PostgreSQL, installida moodul (ĂŒhe kĂ€sklusega) ja edasi on meil uus vaade.

Keskmine pÀringu aeg millisekundites
$ select (sum(total_time) / sum(calls))::numeric(6,3)
from pg_stat_statements;
KÔige aktiivsemalt kirjutavad (shared_buffers) pÀringud
$ select query, shared_blks_dirtied
from pg_stat_statements
where shared_blks_dirtied > 0 order by 2 desc;Mida me sealt vÔtta saame? Kui rÀÀkida lihtsatest asjadest, saame vÔtta keskmise pÀringu tÀitmise aja. Aeg kasvab, see tÀhendab, et PostgreSQL vastab aeglaselt ja midagi tuleb ette vÔtta.
Saame vaadata kÔige aktiivsemaid kirjutavaid tehinguid andmebaasis, mis muudavad andmeid shared buffers. Vaadata, kes me seal andmeid uuendab vÔi kustutab.
Ja saame lihtsalt vaadata erinevaid statistika tulemusi nende pÀringute kohta.

Meie pg_stat_statements Kasutame aruannete koostamiseks. Kord pÀevas kustutame statistika. Kogume seda. Enne jÀrgmist statistika kustutamist koostame aruande. Siin on link aruandele. Saate seda vaadata.

Mida me teeme? Kogume kokku kogu statistika kÔigi pÀringute kohta. SeejÀrel arvutame iga pÀringu individuaalse panuse sellesse kogustatistikasse.
Mida me saame vaadata? Saame vaadata konkreetse tĂŒĂŒpide pĂ€ringute koguaega, vĂ”rrelduna kĂ”igi teiste pĂ€ringutega. Saame vaadata protsessori ja sisend-vĂ€ljundi ressursside kasutamist ĂŒldise pildi taustal. Ja optimeerida neid pĂ€ringuid. Koostame selle aruande pĂ”hjal pĂ€ringute edetabeli ja saame juba mĂ”tteainet, mida optimeerida.

Mida meil on jÀÀnud kÀsitlemata? On veel paar esitlust, mida ma ei hakanud kÀsitlema, kuna aeg on piiratud.
On pgstattuple â see on ka tĂ€iendav moodul standardkomplekti contribs. See vĂ”imaldab hinnata bloat tabelid, nn. tabeli fragmentatsioon. Ja kui fragmentatsioon on suur, tuleb see eemaldada, kasutades erinevaid tööriistu. Ja funktsioon pgstattuple töötab kaua. Ja mida rohkem tabeleid, seda kauem see töötab.

JĂ€rgmine contrib â see on pg_buffercache. See vĂ”imaldab uurida jagatud puhverdamise intensiivsust ja milliseid tabeleid puhver lehtede poolt kasutab. See annab lihtsalt vĂ”imaluse vaadata jagatud puhvrite sisu ja hinnata, mis seal toimub.
JĂ€rgmine moodul â see on pgfincore. See vĂ”imaldab lĂ€bi sĂŒsteemi kutsumise mincore(), tehis-, st see vĂ”imaldab laadida tabelit jagatud puhvrites vĂ”i selle vĂ€lja laadida. See vĂ”imaldab samuti kontrollida operatsioonisĂŒsteemi lehe vahemĂ€lu, st kui palju meie tabel on lehe vahemĂ€lu, jagatud puhvrites ja annab vĂ”imaluse hinnata tabeli koormust.
JĂ€rgmine moodul â pg_stat_kcache. See kasutab samuti sĂŒsteemi kutset getrusage(). Ta tĂ€idab seda enne ja pĂ€rast pĂ€ringu tĂ€itmist. Saadud statistika abil on vĂ”imalik hinnata, kui palju meie pĂ€ring kulutas ketta sisend-vĂ€ljundile, st toimingutele failisĂŒsteemiga ja vaadata protsessori kasutamist. Siiski on moodul noor (khm-khm) ja selle toimimiseks on vajalik PostgreSQL 9.4 ning pg_stat_statements, millest ma varem rÀÀkisin.

Statistika kasutamine on kasulik. Teil ei ole vaja kolmanda osapoole programme. Saate ise sisse vaadata, vaadata, midagi teha, tÀita.
Statistika kasutamine ei ole keeruline, see on tavaline SQL. Te koostate pÀringu, vormistate, saadate ja vaatate.
Statistika aitab vastata kĂŒsimustele. Kui kĂŒsitav kĂŒsimus tekib, pöördute statistikasse â vaatate, teete jĂ€reldusi, analĂŒĂŒsite tulemusi.
Katsuge katsetada. PÀringuid on palju, andmeid on palju. Alati on vÔimalik optimeerida mÔnda juba olemasolevat pÀringut. VÔite teha oma versiooni pÀringust, mis sobib teile paremini kui originaal, ja kasutada seda.

Lingid
Kasulikud lingid, mis artiklis esinesid, mille alusel ettekanne tehti.
Autor kirjutab veel.
(eng)
Statistika Koguja
SĂŒsteemi Administreerimise Funktsioonid
Contrib moodulid
SQL utiliid ja SQL koodinÀidised
AitÀh kÔigile tÀhelepanu eest!
Allikas: habr.com
