sql >> Databasteknik >  >> RDS >> PostgreSQL

Cachning i PostgreSQL

Cachar...!!, det är lite svårt att gå kortfattat med en enda artikel. Men ska försöka dela med mig av min kunskap som jag lärt mig från Heikki / Robert Haas / Bruce Momjian kortfattat. I PostgreSQL finns det två lager, PG delade buffertar och OS Page cache, all läs/skriv bör passera genom OS cache (ingen förbikoppling tills nu). Postgres skriver data på OS Page Cache och bekräftar för användaren när den har skrivit till disk, senare OS-cache-skrivning till fysisk disk i sin egen takt. PG delade buffertar har ingen kontroll över OS Page Cache och den vet inte ens vad som finns i OS-cachen. Så de flesta av rekommendationerna ges av Postgres DBA:s/Professional's att ha snabbare DISK / bättre cache.

Cachar/buffertar i PostgreSQL är starkare som andra databaser och mycket sofistikerade. Som jag kommer från Oracle-bakgrunden (även tänkesätt...:)), så min fråga är vem jag lärde mig av hur/när/vad/varför etc., angående databasbuffertcache, fästa buffertar, spolning av databasbuffertarcache, förladdning av databas etc., Jag fick alla mina svar från dem, men tillvägagångssättet är lite annorlunda. Även om mina frågor var problematiska, svarade de med stort tålamod och förtydligade mig i god utsträckning, vilket resulterar i att du läser den här bloggen... :)..

På vissa lärdomar (fortfarande inlärning) ritade jag en liten översikt över hur dataflödet mellan minne till disk i Postgres och även några av de viktiga verktygen och den NYA patchen av Robert Haas(pg_prewarm) .

pg_buffercache
En bidragsmodul som berättar vad som finns i PostgreSQL buffertcache. Installation nedan:-

postgres=# SKAPA EXTENTION pg_buffercache;

pgfincore
Den har en funktion för att ge information om vilken data i OS Page Cache. Pgfincore, modul blir väldigt praktisk när den klubbas med pg_buffercache, nu kan man få PG buffertcache och OS Page Cache information tillsammans. Tack till Cerdic Villemain. Pgfincore, backbone är fadvise, fincore som är linux ftools. Du kan också använda fincore/fadvise genom att installera källkod. Två saker, du kan använda pgfincore bidragsmodul eller ftools båda resulterar på samma sätt. Jag provade båda, de är helt enkelt fantastiska.

Installation:
Ladda ner den senaste versionen:http://pgfoundry.org/frs/download.php/3186/pgfincore-v1.1.1.tar.gz
Som root-användare:
export PATH=/usr/local/pgsql91/bin:$PATH //Sätt sökvägen till punkten pg_config.
tar -xvf pgfincore-v1.1.1.tar.gz
cd pgfincore-1.1.1
make clean
make
make install

Anslut nu till PG och kör nedan kommando

postgres=# CREATE EXTENSION pgfincore;

pg_prewarm
Förladda relationen/indexet till PG buffertcache. Är det möjligt i PostgreSQL? åh ja, tack till Robert Haas , som nyligen har skickat patch till communityn, förhoppningsvis kan den vara tillgänglig i PG 9.2 eller PG 9.3. Du kan dock använda patchen för att testa på PG 9.1.

pg_prewarm har tre MODE:

  1. FÖRHÄMTA: Hämtar datablock asynkront till endast OS-cache, inte till PG-buffertar (endast träffar OS-cache)
  2. LÄS: Läser alla block i dummybuffert och tvingar in i OS-cache. (endast träffar OS-cache)
  3. BUFFERT: läser alla block eller blockintervall i databasbuffertcache.

Installation:
Jag använder pg_prewarm patch på min PG-källinstallation, du måste justera enligt dina inställningar.

  1. Utar plats för PG-källa:/usr/local/src/postgresql-9.1.3
  2. PG-installationslocatin:/usr/local/pgsql91
  3. Alla nedladdningar Plats:/usr/local/src

Obs:Installera PG innan du använder pg_prewarm patch.

1. Ladda ner patchen till /usr/local/src/ location
http://archives.postgresql.org/pgsql-hackers/2012-03/binRVNreQMnK4.bin
Patch bifogad e-post:
http://archives.postgresql.org/message-id/CA+TgmobRrRxCO+t6gcQrw_dJw+Uf9ZEdwf9beJnu+RB5TEBjEw@mail.gmail.com
2. Efter nedladdning, gå till PG-källans plats och följ stegen.

# cd /usr/local/src/postgresql-9.1.3
# patch -p1 <../pg_prewarm.bin (jag har bytt namn efter nedladdning)
# make -C contrib/pg_prewarm
# make -C contrib/pg_prewarm install

3. Kommandot ovan skapar filer under $PGPATH/contrib/extension. Nu är du redo att lägga till bidragsmodulen.

postgres=# skapa EXTENTION pg_prewarm;
SKAPA TILLÄGG
postgres=# dx
Lista över installerade tillägg
Namn | Version | Schema | Beskrivning
----------------+---------+------------+----- ----------------------------------
pg_buffercache | 1.0 | offentliga | undersök den delade buffertcachen
pg_prewarm | 1.0 | offentliga | prewarm relation data
pgfincore | 1.1.1 | offentliga | undersöka och hantera OS-buffertcachen
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedurspråk
(4 rader)

Dokumentation:
/usr/local/src/postgresql-9.1.3/doc/src/sgml
[ root@localhost sgml]# ll pgpre*
-rw-r--r-- 1 root root 2481 apr 10 10:15 pgprewarm.sgml

dstat
En kombination av vmstat, iostat, netstat, top, etc., verktyg tillsammans i ett "dstat" linux-kommando. När databasen beter sig ovanligt, för att veta orsaken från OS-nivå, öppnar vi några terminaler för att hämta process, minne, diskläsning/skrivning, nätverksinformation, vilket är lite jobbigt att blanda mellan fönstren. Så, dstat har flera alternativ med sig, vilket hjälper till att visa alla kommandon i en utdata och ett fönster.

Installation:
Dstat-nedladdningslänk:(RHEL 6)
wget http://pkgs.repoforge.org/dstat/dstat-0.7.2-1.el6.rfx.noarch.rpm
eller
yum installera dstat
Dokumentation:http://dag.wieers.com/home-made/dstat/

Linux ftools
Den är designad för att arbeta med moderna linux-systemanrop inklusive mincore, fallocate, fadvise, etc. Ftools hjälper dig att ta reda på vilka filer som finns i OS-cachen. Med hjälp av perl/python-skript kan du hämta OS-sidans cacheinformation på objektfiler (pg_class.relfilenode). pg_fincore är baserad på detta. Du kan använda pgfincore- eller ftools-skript.

Installation:
Ladda ner tar.gz från länken.
https://github.com/david415/python-ftools

cd python-ftools
python setup.py build
exportera PYTHONPATH=build/lib.linux-x86_64-2.5
python setup.py install

Obs:Du måste ha python &psycopg2 installerat innan installera python-ftools.

Nu är vi alla redo att fortsätta med exempel för att kontrollera med verktygen och verktygen. I mitt exempel har jag en tabell, den har ett index och en sekvens med 100+ MB data i den.

postgres=# d+ cache
Tabell "public.cache"
Kolumn | Skriv | Modifierare | Förvaring | Beskrivning
--------+---------+-------------------------------- ---------------+----------+-------------
namn | text | | utökad |
kod | heltal | | vanligt |
id | heltal | default nextval('icache_seq'::regclass) | vanligt |
Index:
"icache" bträd (kod)
Har OID:nej

Fråga för att veta storleken som upptas av tabell, sekvens och dess index.

postgres=# SELECT c.relname AS object_name,
CASE när c.relkind='r' sedan 'table'
när c.relkind='i' sedan 'index'
när c.relkind='S' sedan 'sequence'
else 'others'
END AS type,pg_relation_size(c.relname::text) AS size, pg_size_pretty(pg_relation_size(c.relname::text) )) SOM pretty_size
FRÅN pg_class c
GÅ MED i pg_roles r PÅ r.oid =c.relowner
LEFT JOIN pg_namespace n PÅ n.oid =c.relnamespace
VAR (c. relkind =ALLA (ARRAY['r'::"char", 'i'::"char", 'S'::"char",''::"char"])) OCH n.nspname ='public ';

objektnamn | typ | storlek | pretty_size
--------------+------------------------ ----
icache_seq | sekvens | 8192 | 8192 byte
cache | bord | 83492864 | 80 MB
icache | index | 35962880 | 34 MB
(3 rader)

Total objektstorlek 'cache'

postgres=# välj pg_size_pretty(pg_total_relation_size('cache'));
pg_size_pretty
----------------
114 MB
(1 rad)

Jag har skrivit en liten fråga genom att klubba pgfincore och pg_buffercache för att hämta information från PG Buffer &OS Page cache. Jag kommer att använda den här frågan genom hela mitt exempel, bara klistra in den här frågans utdata.

välj rpad(c.relname,30,' ') som Object_Name,
case när c.relkind='r' sedan 'Table' när c.relkind='i' sedan 'Index' annars 'Övrigt' ' sluta som Object_Type,
rpad(count(*)::text,5,' ') som "PG_Buffer_Cache_usage(8KB)",
split_part(pgfincore(c.relname::text)::text ,','::text,5) som "OS_Cache_usage(4KB)"
från pg_class c inner join pg_buffercache b på b.relfilenode=c.relfilenode
inner join pg_database d on (b.reldatabase=d.oid och d.datname=current_database() och c.relnamespace=(välj oid från pg_namespace där nspname='public'))
gruppera efter c.relname,c.relkind
ordning efter "PG_Buffer_Cache_usage (8KB)"
beskrivningsgräns 10;

objektnamn | objekttyp | PG_Buffer_Cache_usage(8KB) ​​| OS_Cache_usage(4KB)
-------+-------------+-------------------- --------------+---------------------
(0 rader)

Obs:Jag har studsat klustret för att spola PG-buffertar &OS Page Cache. Så, ingen data i någon cache/buffert.

Förladdning av relation/index med pg_prewarm:
Innan jag studsade klustret har jag avfyrat en sekventiell genomsökning av hela tabellen på "Cache"-tabellen och noterat tiden innan relationen/indexet värms upp.

postgres=# förklara analysera välj * från cache;
FRÅGEPLAN
-------------------------------- -------------------------------------------------- --------------------------------------
Seq Scan på cache (kostnad=0,00. .26192.00 rader=1600000 bredd=19) (faktisk tid=0.033..354.691 rader=1600000 loopar=1)
Total körtid:427.769 ms
(2 rader)
Låter värma relation/index/sekvens med hjälp av pg_prewarm och kontrollera frågeplan.

postgres=# välj pg_prewarm('cache','main','buffer',null,null);
pg_prewarm
-------
10192
(1 rad)
postgres=# välj pg_prewarm('icache','main','buffer',null,null);
pg_prewarm
---- --------
4390
(1 rad)

Utdata från kombinerade buffertar:
objektnamn | objekttyp | PG_Buffer_Cache_usage(8KB) ​​| OS_Cache_usage(4KB)
-------+-------------+-------------------- --------------+----------------------------
icache | Index | 4390 | 8780
cache | Tabell | 10192 | 20384
(2 rader)

pgfincore-utgång:

postgres=# välj relname,split_part(pgfincore(c.relname::text)::text,','::text,5) som "In_OS_Cache" från pg_class c där relname ilike '%cache%';
relname | In_OS_Cache
-------------+------------
icache_seq | 2
cache | 20384
icache | 8780
(3 rader)

eller för varje objekt.

postgres=# välj * från pgfincore('cache');
relpath | segment | os_sida_storlek | rel_os_pages | pages_mem | group_mem | os_sidor_gratis | databit
----------------+---------+--------------+- --------------+------------+------------+------------- ---+---------
bas/12780/16790 | 0 | 4096 | 20384 | 20384 | 1 | 316451 |
(1 rad)

För att hämta liknande information med python-ftools script måste du känna till objektets relfilenodnummer, kolla nedan.

postgres=# välj relfilenode,relname från pg_class där relname ilike '%cache%';
relfilenode | relname
-------------+----------------
16787 | icache_seq /// du kan utesluta sekvens.
16790 | cache /// tabell
16796 | icache /// index
(3 rader)

med python-ftools-skript

Är det inte intressant...!!!!.
Jämför nu förklaraplanen efter uppvärmning av bordet till buffert.

postgres=# förklara analysera välj * från cache;
FRÅGEPLAN
-------------------------------- -------------------------------------------------- --------------------------------------
Seq Scan på cache (kostnad=0,00. .26192.00 rader=1600000 bredd=19) (faktisk tid=0.016..141.804 rader=1600000 loopar=1)
Total körtid:215.100 ms
(2 rader)
Hur man spolar/förvärmer relation/index i OS-cache?
Med pgfadvise kan du förladda eller tömma relationen från OS-cachen. För mer information, skriv df pgfadvise* i terminal för alla funktioner relaterade till pgfadvise. Nedan finns ett exempel på hur man tömt OS-cachen.

postgres=# välj * från pgfadvise_dontneed('cache');
relpath | os_sida_storlek | rel_os_pages | os_sidor_gratis
----------------+--------------+---------------- ---+---------------
base/12780/16790 | 4096 | 20384 | 178145
(1 rad)
postgres=# välj * från pgfadvise_dontneed('icache');
relpath | os_sida_storlek | rel_os_pages | os_sidor_gratis
----------------+--------------+---------------- ---+--------------
base/12780/16796 | 4096 | 8780 | 187166
(1 rad)
postgres=# välj relname,split_part(pgfincore(c.relname::text)::text,','::text,5) som "In_OS_Cache" från pg_class c där relname ilike '%cache%';
relname | In_OS_Cache
-------------+------------
icache_seq | 0
cache | 0
icache | 0
(3 rader)

Medan dessa saker pågår i ett fönster kan du kontrollera läs/skrivförhållandet genom att använda dstat. För fler alternativ använd dstat –list
dstat -s –top-io –top-bio –top-mem

Förladdningsintervall för block med pg_prewarm range-funktionalitet.
Anta att du av någon anledning vill studsa klustret, men ett stort bord som är i buffert fungerar bra. När du studsar kommer ditt bord inte längre i buffertar, för att komma tillbaka till det ursprungliga tillståndet som det var innan det studsade måste du veta hur många tabellblock som fanns i buffertar och förladda dem med alternativet pg_prewarm range.

Jag har skapat en tabell genom att fråga pg_buffercache och senare har jag skickat information om blockintervall till pg_prewarm. Genom detta är delade buffertar tillbaka med tabellen tidigare laddad i den. Se exemplet.

välj c.relname,count(*) som buffertar från pg_class c 
inner join pg_buffercache b på b.relfilenode=c.relfilenode och c.relname ilike '%cache%'
inner join pg_database d on (b.reldatabase=d.oid och d.datname=current_database())
gruppera efter c.relname
ordning efter buffertar desc;
relname | buffertar
--------+---------
cache | 10192
icache | 4390
(2 rader)
Obs:Dessa är blocken i bufferten.

postgres=# skapa tabell blocks_in_buff (relation, fork, block) som välj c.oid::regclass::text, case b.relforknumber när 0 sedan 'main' när 1 sedan 'fsm' när 2 sedan 'vm' slutar, b.relblocknumber från pg_buffercache b, pg_class c, pg_database d där b.relfilenode =c.relfilenode och b.reldatabase =d.oid och d.datname =current_database() och b.relforknumber in (0, 1, 2);
SELECT 14716

Studsa klustret och förladda intervallet av block relaterade till tabellen i buffertar från "blocks_in_buff".

postgres=# välj summa(pg_prewarm(relation, gaffel, 'buffer', block, block)) från blocks_in_buff;
summa
-------
14716
(1 rad)

postgres=# välj c.relname,count(*) som buffertar från pg_class c
inner join pg_buffercache b på b.relfilenode=c.relfilenode och c. relname ilike '%cache%'
inner join pg_database d on (b.reldatabase=d.oid och d.datname=current_database())
gruppera efter c.relname
ordna efter buffertar desc;
relname | buffertar
--------+---------
cache | 10192
icache | 4390
(2 rader)

Se, min shared_buffer's är tillbaka i spelet.

Njut av…!!! återkommer med mer intressanta saker. Skriv dina kommentarer.


  1. Postgres ändrar sekvensen manuellt

  2. Hur man kontrollerar om mysql-databas finns

  3. Oracle:flera tabelluppdateringar => ORA-01779:kan inte ändra en kolumn som mappas till en icke-nyckelbevarad tabell

  4. Hur man formaterar siffror i PostgreSQL