sql >> Database teknologi >  >> RDS >> PostgreSQL

Caching i PostgreSQL

Caching...!!, det er lidt svært at kortfatte med en enkelt artikel. Men vil prøve at dele min viden, jeg har lært fra Heikki / Robert Haas / Bruce Momjian kort sagt. I PostgreSQL er der to lag, delte PG-buffere og OS Page cache, enhver læsning/skrivning skal passere gennem OS-cache (ingen omgåelse indtil nu). Postgres skriver data på OS Page Cache og bekræfter til brugeren, som den har skrevet til disk, senere OS-cache-skrivning til fysisk disk i sit eget tempo. PG-delte buffere har ingen kontrol over OS Page Cache, og den ved ikke engang, hvad der er i OS-cachen. Så det meste af anbefalingen er givet af Postgres DBA'er/Professional'er om at have hurtigere DISK / bedre cache.

Caches/buffere i PostgreSQL er stærkere som andre databaser og meget sofistikerede. Som jeg kommer fra Oracle-baggrund (mindset også...:)), så mit spørgsmål er, hvem jeg lærte af, hvordan/hvornår/hvad/hvorfor osv., vedrørende databasebuffercache, fastgjorte buffere, Flushing databasebuffercache, forudindlæsning af database osv., Jeg fik alle mine svar fra dem, men tilgangen er en smule anderledes. Selvom mine spørgsmål var uklare, besvarede de med stor tålmodighed og præciserede mig i god udstrækning, hvilket resulterer i, at du læser denne blog…. :)..

På nogle læringer (stadig læring) tegnede jeg en lille oversigt over, hvordan data flyder mellem hukommelse til disk i Postgres og også nogle af de vigtige værktøjer og NY patch af Robert Haas(pg_prewarm) .

pg_buffercache
Et bidragsmodul, som fortæller, hvad der er i PostgreSQL-buffercachen. Installation nedenfor:-

postgres=# OPRET UDVIDELSE pg_buffercache;

pgfincore
Den har en funktionalitet til at give information om hvilke data i OS Page Cache. Pgfincore, modul bliver meget praktisk, når det er clubbed med pg_buffercache, nu kan man få PG buffer cache &OS Page Cache information sammen. Tak til Cerdic Villemain. Pgfincore, backbone er fadvise, fincore som er linux ftools. Du kan også bruge fincore/fadvise ved at installere source. To ting, du kan bruge pgfincore bidragsmodul eller ftools, begge resulterer det samme. Jeg prøvede begge, de er simpelthen fantastiske.

Installation:
Download den seneste version:http://pgfoundry.org/frs/download.php/3186/pgfincore-v1.1.1.tar.gz
Som root-bruger:
eksport PATH=/usr/local/pgsql91/bin:$PATH //Sæt stien til punkt pg_config.
tar -xvf pgfincore-v1.1.1.tar.gz
cd pgfincore-1.1.1
make clean
make
make install

Tilslut nu til PG og kør nedenstående kommando

postgres=# CREATE EXTENSION pgfincore;

pg_prewarm
Forudindlæsning af relationen/indekset i PG buffer cache. Er det muligt i PostgreSQL? åh ja, tak til Robert Haas , som for nylig har indsendt patch til fællesskabet, forhåbentlig er den tilgængelig i PG 9.2 eller PG 9.3. Du kan dog bruge patchen til din test på PG 9.1.

pg_prewarm har tre MODE:

  1. PREFETCH: Henter datablokke asynkront kun til OS-cache, ikke til PG-buffere (hits kun OS-cache)
  2. LÆS: Læser alle blokke ind i dummy-buffer og tvinger ind i OS-cache. (hit kun OS cache)
  3. BUFFER: læser alle blokke eller række af blokke ind i databasebuffercachen.

Installation:
Jeg anvender pg_prewarm-patch på min PG-kildeinstallation, du skal justere i henhold til din opsætning.

  1. Utar placering af PG-kilde:/usr/local/src/postgresql-9.1.3
  2. PG-installationslocatin:/usr/local/pgsql91
  3. Alle downloads Placering:/usr/local/src

Bemærk:Installer PG før du anvender pg_prewarm patch.

1. Download patchen til /usr/local/src/ location
http://archives.postgresql.org/pgsql-hackers/2012-03/binRVNreQMnK4.bin
Patch vedhæftet e-mail:
http://archives.postgresql.org/message-id/CA+TgmobRrRxCO+t6gcQrw_dJw+Uf9ZEdwf9beJnu+RB5TEBjEw@mail.gmail.com
2. Efter download skal du gå til PG-kildeplaceringen og følge trinene.

# cd /usr/local/src/postgresql-9.1.3
# patch -p1 <../pg_prewarm.bin (jeg har omdøbt efter download)
# make -C contrib/pg_prewarm
# make -C contrib/pg_prewarm install

3. Ovenstående kommando vil oprette filer under $PGPATH/contrib/extension. Nu er du klar til at tilføje bidragsmodulet.

postgres=# create EXTENTION pg_prewarm;
CREATE EXTENTION
postgres=# dx
Liste over installerede udvidelser
Navn | Version | Skema | Beskrivelse
----------------+---------+------------- -----------------------------------
pg_buffercache | 1,0 | offentlig | undersøg den delte buffer cache
pg_prewarm | 1,0 | offentlig | prewarm relation data
pgfincore | 1.1.1 | offentlig | undersøg og administrer os buffer cachen
plpgsql | 1,0 | pg_katalog | PL/pgSQL proceduresprog
(4 rækker)

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 af vmstat,iostat,netstat,top osv., værktøj sammen i en "dstat" linux kommando. Når databasen opfører sig usædvanligt, for at kende årsagen fra OS-niveau, åbner vi et par terminaler for at trække proces, hukommelse, disk læse/skrive, netværksinformationer, hvilket er lidt smertefuldt at blande mellem vinduer. Så dstat har flere muligheder med i sig, hvilket hjælper med at vise alle kommandoer i et output i et vindue.

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

Linux ftools
Den er designet til at arbejde med moderne linux-systemkald, inklusive mincore, fallocate, fadvise osv. Ftools hjælper dig med at finde ud af, hvilke filer der er i OS-cachen. Ved at bruge perl/python-scripts kan du hente OS-sidecacheoplysninger på objektfiler (pg_class.relfilenode). pg_fincore er baseret på dette. Du kan bruge pgfincore eller ftools scripts.

Installation:
Download tar.gz fra linket.
https://github.com/david415/python-ftools

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

Bemærk:Du skal have python &psycopg2 installeret før installation af python-ftools.

Nu er vi alle klar til at fortsætte med eksemplet for at tjekke med værktøjerne og hjælpeprogrammerne. I mit eksempel har jeg en tabel, den har et indeks og en sekvens med 100+ MB data i den.

postgres=# d+ cache
Tabel "public.cache"
Kolonne | Skriv | Modifikatorer | Opbevaring | Beskrivelse
--------+---------+-------------------------------- ---------------+-----------+-------------
navn | tekst | | udvidet |
kode | heltal | | almindelig |
id | heltal | default nextval('icache_seq'::regclass) | almindeligt |
Indekser:
"icache" btree (kode)
Har OID'er:nej

Forespørgsel for at kende størrelsen optaget af tabel, sekvens og dens indeks.

postgres=# SELECT c.relname AS object_name,
CASE, når c.relkind='r' derefter 'table'
når c.relkind='i' derefter 'index'
når c.relkind='S' så '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
FRA pg_class c
JOIN pg_roles r ON r.oid =c.relowner
LEFT JOIN pg_namespace n ON n.oid =c.relnamespace
HVOR (c. relkind =ENHVER (ARRAY['r'::"char", 'i'::"char", 'S'::"char",''::"char"])) OG n.nspname ='public ';

objektnavn | type | størrelse | pretty_size
----------------------------- ----
icache_seq | rækkefølge | 8192 | 8192 bytes
cache | bord | 83492864 | 80 MB
icache | indeks | 35962880 | 34 MB
(3 rækker)

Samlet objektstørrelse 'cache'

postgres=# select pg_size_pretty(pg_total_relation_size('cache'));
pg_size_pretty
----------------
114 MB
(1 række)

Jeg har skrevet en lille forespørgsel ved at clubbing pgfincore og pg_buffercache for at trække information fra PG Buffer &OS Page cache. Jeg vil bruge denne forespørgsel gennem mit eksempel, kun indsætte denne forespørgselsudgang.

vælg rpad(c.relname,30,' ') som Object_Name,
case, når c.relkind='r' derefter 'Tabel', når c.relkind='i' derefter 'Index' ellers 'Andet' ' end as Object_Type,
rpad(count(*)::text,5,' ') as "PG_Buffer_Cache_usage(8KB)",
split_part(pgfincore(c.relname::text)::text ,','::text,5) som "OS_Cache_usage(4KB)"
fra pg_class c indre join pg_buffercache b på b.relfilenode=c.relfilenode
indre join pg_database d on (b.reldatabase=d.oid og d.datname=current_database() og c.relnamespace=(vælg oid fra pg_namespace hvor nspname='public'))
grupper efter c.relname,c.relkind
ordner efter "PG_Buffer_Cache_usage (8KB)"
beskrivelsesgrænse 10;

objektnavn | objekttype | PG_Buffer_Cache_usage(8KB) ​​| OS_Cache_usage(4KB)
-------+------+-------------------- --------------+---------------------
(0 rækker)

Bemærk:Jeg har afvist klyngen for at tømme PG-buffere &OS Page Cache. Så ingen data i nogen cache/buffer.

Forudindlæser relation/indeks ved hjælp af pg_prewarm:
Før jeg afviste klyngen, har jeg affyret en sekventiel scanningsforespørgsel i hele tabellen på "Cache"-tabellen og noteret tiden, der er før opvarmning af relationen/indekset.

postgres=# forklar analyse vælg * fra cache;
FORSPØRGSPLAN
-------------------------------- -------------------------------------------------- --------------------------------------
Seq Scan på cache (pris=0,00. .26192.00 rows=1600000 width=19) (faktisk tid=0.033..354.691 rows=1600000 loops=1)
Samlet køretid:427.769 ms
(2 rækker)
Lader varme relation/indeks/sekvens ved hjælp af pg_prewarm og tjekke forespørgselsplan.

postgres=# vælg pg_prewarm('cache','main','buffer',null,null);
pg_prewarm
-------
10192
(1 række)
postgres=# vælg pg_prewarm('icache','main','buffer',null,null);
pg_prewarm
---- --------
4390
(1 række)

Output af kombinerede buffere:
objektnavn | objekttype | PG_Buffer_Cache_usage(8KB) ​​| OS_Cache_usage(4KB)
-------+------+-------------------- --------------+----------------------------
icache | Indeks | 4390 | 8780
cache | Tabel | 10192 | 20384
(2 rækker)

pgfincore output:

postgres=# vælg relname,split_part(pgfincore(c.relname::text)::text,','::text,5) som "In_OS_Cache" fra pg_class c hvor relname ilike '%cache%';
relname | In_OS_Cache
-------------+------------
icache_seq | 2
cache | 20384
icache | 8780
(3 rækker)

eller for hvert objekt.

postgres=# vælg * fra pgfincore('cache');
relpath | segment | os_side_størrelse | rel_os_pages | pages_mem | gruppe_mem | os_sider_gratis | databit
----------------+---------+-------------+- --------------+------------+------------+------- ---+---------
base/12780/16790 | 0 | 4096 | 20384 | 20384 | 1 | 316451 |
(1 række)

For at hente lignende information ved hjælp af python-ftools script skal du kende objekternes relfilenode nummer, se nedenfor.

postgres=# vælg relfilenode,relname fra pg_class hvor relname ilike '%cache%';
relfilenode | relname
-------------+----------------
16787 | icache_seq /// du kan udelukke sekvens.
16790 | cache /// tabel
16796 | icache /// index
(3 rækker)

ved hjælp af python-ftools script

Er det ikke interessant...!!!!.
Sammenlign nu forklaringsplanen efter opvarmning af bordet til buffer.

postgres=# forklar analyse vælg * fra cache;
FORSPØRGSPLAN
-------------------------------- -------------------------------------------------- --------------------------------------
Seq Scan på cache (pris=0,00. .26192.00 rows=1600000 width=19) (faktisk tid=0.016..141.804 rows=1600000 loops=1)
Samlet køretid:215.100 ms
(2 rækker)
Hvordan skylles/forvarmes relation/indeks i OS-cache?
Ved at bruge pgfadvise kan du forudindlæse eller tømme relationen fra OS-cachen. For mere information, skriv df pgfadvise* i terminal for alle funktioner relateret til pgfadvise. Nedenfor er et eksempel på fjernelse af OS-cachen.

postgres=# vælg * fra pgfadvise_dontneed('cache');
relpath | os_side_størrelse | rel_os_pages | os_sider_gratis
------------------------+--------------+---------------- ---+--------------
base/12780/16790 | 4096 | 20384 | 178145
(1 række)
postgres=# vælg * fra pgfadvise_dontneed('icache');
relpath | os_side_størrelse | rel_os_pages | os_sider_gratis
------------------------+--------------+---------------- ---+--------------
base/12780/16796 | 4096 | 8780 | 187166
(1 række)
postgres=# vælg relname,split_part(pgfincore(c.relname::text)::text,','::text,5) som "In_OS_Cache" fra pg_class c hvor relname ilike '%cache%';
relname | In_OS_Cache
-------------+------------
icache_seq | 0
cache | 0
icache | 0
(3 rækker)

Mens disse ting foregår i et vindue, kan du kontrollere læse/skriveforholdet ved at bruge dstat. For flere muligheder, brug dstat –list
dstat -s –top-io –top-bio –top-mem

Forudindlæsning af rækkevidde af blokke ved hjælp af funktionaliteten pg_prewarm range.
Antag, at du af en eller anden grund ønsker at hoppe klyngen, men en af ​​de store borde, som er i buffer, klarer sig godt. Når du hopper, er dit bord ikke længere i buffere, for at vende tilbage til den oprindelige tilstand, som det var før hoppet, skal du vide, hvor mange tabelblokke der var i buffere og forudindlæse dem ved at bruge pg_prewarm range option.

Jeg har oprettet en tabel ved at forespørge pg_buffercache, og senere har jeg sendt blokområdeinformation til pg_prewarm. Dermed er delte buffere tilbage med tabellen tidligere indlæst i den. Se eksemplet.

vælg c.relname,count(*) som buffere fra pg_class c 
indre join pg_buffercache b på b.relfilenode=c.relfilenode og c.relname ilike '%cache%'
indre join pg_database d on (b.reldatabase=d.oid og d.datname=current_database())
grupper efter c.relname
rækkefølge efter buffere desc;
relname | buffere
--------+---------
cache | 10192
icache | 4390
(2 rækker)
Bemærk:Disse er blokkene i buffer.

postgres=# opret tabel blocks_in_buff (relation, fork, block) som vælg c.oid::regclass::text, case b.relforknumber når 0 derefter 'main' når 1 så 'fsm' når 2 så 'vm' slutter, b.relblocknumber fra pg_buffercache b, pg_class c, pg_database d hvor b.relfilenode =c.relfilenode og b.reldatabase =d.oid og d.datname =current_database() og b.relforknumber i (0, 1, 2);
SELECT 14716

Bounce klyngen og forudindlæs rækken af ​​blokke relateret til tabellen i buffere fra "blocks_in_buff".

postgres=# vælg sum(pg_prewarm(relation, gaffel, 'buffer', blok, blok)) fra blocks_in_buff;
sum
-------
14716
(1 række)

postgres=# vælg c.relname,count(*) som buffere fra pg_class c
indre join pg_buffercache b på b.relfilenode=c.relfilenode og c. relname ilike '%cache%'
inner join pg_database d on (b.reldatabase=d.oid og d.datname=current_database())
grupper efter c.relname
ordnet efter buffere desc;
relname | buffere
--------+---------
cache | 10192
icache | 4390
(2 rækker)

Se, min shared_buffer's er tilbage i spil.

God fornøjelse…!!! vender tilbage med flere interessante ting. Skriv dine kommentarer.


  1. Hvordan bestiller man efter antal i SQL?

  2. Postgresql vælg indtil et bestemt totalbeløb er nået

  3. Skal jeg bruge makroer eller VBA-kode?

  4. SQLite MAX