Cache/buffery v PostgreSQL jsou silnější jako ostatní databáze a vysoce sofistikované. Vzhledem k tomu, že jsem z prostředí Oracle (také nastavení mysli…:) ), moje otázka je, od koho jsem se dozvěděl, jak/kdy/co/proč atd., pokud jde o mezipaměť vyrovnávací paměti databáze, připnuté vyrovnávací paměti, vyprázdnění mezipaměti vyrovnávací paměti databáze, předběžné načítání databáze atd., Dostal jsem od nich všechny odpovědi, ale přístup je trochu jiný. I když byly mé otázky otravné, odpovídali s velkou trpělivostí a objasňovali mě do té míry, že ve výsledku čtete tento blog…. :)..
Při některých učeních (stále se učím) jsem nakreslil malý přehled toho, jak tok dat mezi pamětí na disk v Postgresu, a také některé důležité nástroje a NOVÝ patch od Roberta Haase(pg_prewarm) .
pg_buffercache
Modul contrib, který říká, co je ve vyrovnávací paměti PostgreSQL. Instalace níže:-
postgres=# CREATE EXTENSION pg_buffercache;
pgfincore
Má funkci, která poskytuje informace o tom, jaká data v mezipaměti stránek OS. Modul Pgfincore se stává velmi užitečným, když je spojen s pg_buffercache, nyní lze získat informace o mezipaměti PG a mezipaměti OS stránky. Díky Cerdic Villemain. Pgfincore, páteř je fadvise, fincore, což jsou linuxové nástroje. Můžete také použít fincore/fadvise instalací zdrojového kódu. Dvě věci, můžete použít modul pgfincore contrib nebo ftools, oba mají stejný výsledek. Vyzkoušel jsem oba, jsou prostě úžasné.
Installation:
Download the latest version: http://pgfoundry.org/frs/download.php/3186/pgfincore-v1.1.1.tar.gz
As root user:
export PATH=/usr/local/pgsql91/bin:$PATH //Set the path to point pg_config.
tar -xvf pgfincore-v1.1.1.tar.gz
cd pgfincore-1.1.1
make clean
make
make install
Now connect to PG and run below command
postgres=# CREATE EXTENSION pgfincore;
pg_prewarm
Předběžné načtení vztahu/indexu do vyrovnávací paměti PG. Je to možné v PostgreSQL? ach ano, díky Robertu Haasovi , který nedávno odeslal patch komunitě, doufejme, že by mohl být dostupný v PG 9.2 nebo PG 9.3. Můžete však použít opravu pro testování na PG 9.1.
pg_prewarm má tři REŽIMY:
- PŘEDNAČET: Načítání bloků dat asynchronně pouze do mezipaměti operačního systému, nikoli do vyrovnávacích pamětí PG (pouze mezipaměť operačního systému)
- ČTĚTE: Načte všechny bloky do fiktivní vyrovnávací paměti a vloží je do mezipaměti operačního systému. (nalezne pouze mezipaměť operačního systému)
- BUFFER: načte všechny bloky nebo rozsah bloků do mezipaměti databáze.
Instalace:
Na instalaci zdroje PG aplikuji opravu pg_prewarm, musíte ji upravit podle svého nastavení.
- Umístění zdroje PG v untar:/usr/local/src/postgresql-9.1.3
- Umístění instalace PG:/usr/local/pgsql91
- Umístění všech stažených souborů:/usr/local/src
Poznámka:Před použitím opravy pg_prewarm nainstalujte PG.
1. Stáhněte si opravu do umístění /usr/local/src/
http://archives.postgresql.org/pgsql-hackers/2012-03/binRVNreQMnK4.bin
E-mail přiložený k opravě:
http://archives.postgresql.org/message-id/CA+TgmobRrRxCO+t6gcQrw_dJw+Uf9ZEdwf9beJnu+RB5TEBjEw@mail.gmail.com
2. Po stažení přejděte do umístění zdroje PG a postupujte podle kroků.
# cd /usr/local/src/postgresql-9.1.3
# patch -p1 < ../pg_prewarm.bin (I have renamed after download)
# make -C contrib/pg_prewarm
# make -C contrib/pg_prewarm install
3. Výše uvedený příkaz vytvoří soubory pod $PGPATH/contrib/extension. Nyní jste připraveni přidat modul contrib.
postgres=# create EXTENSION pg_prewarm;
CREATE EXTENSION
postgres=# dx
List of installed extensions
Name | Version | Schema | Description
----------------+---------+------------+----------------------------------------
pg_buffercache | 1.0 | public | examine the shared buffer cache
pg_prewarm | 1.0 | public | prewarm relation data
pgfincore | 1.1.1 | public | examine and manage the os buffer cache
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(4 rows)
Documentation:
/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
Kombinace nástrojů vmstat,iostat,netstat,top atd. v jednom linuxovém příkazu „dstat“. Když se databáze chová nezvykle, abychom věděli příčinu z úrovně OS, otevřeme několik terminálů pro stahování procesů, paměti, čtení/zápisu disku, síťových informací, což je trochu bolestné přehazovat mezi okny. Takže dstat má v sobě několik možností, což pomáhá zobrazit všechny příkazy v jednom výstupním okně.
Installation:
Dstat download link: (RHEL 6)
wget http://pkgs.repoforge.org/dstat/dstat-0.7.2-1.el6.rfx.noarch.rpm
or
yum install dstat
Documentation: http://dag.wieers.com/home-made/dstat/
Ftools Linux
Je navržen pro práci s moderními systémovými voláními linuxu včetně mincore, fallocate, fadvise atd. Ftools vám pomůže zjistit, jaké soubory jsou v mezipaměti operačního systému. Pomocí skriptů perl/python můžete získat informace z mezipaměti stránky OS na souborech objektů (pg_class.relfilenode). pg_fincore je založen na tomto. Můžete použít skripty pgfincore nebo ftools.
Installation:
Download the tar.gz from the link.
https://github.com/david415/python-ftools
cd python-ftools
python setup.py build
export PYTHONPATH=build/lib.linux-x86_64-2.5
python setup.py install
Note: You need to have python & psycopg2 installed before installing python-ftools.
Nyní jsme všichni připraveni pokračovat příkladem a zkontrolovat pomocí nástrojů a utilit. V mém příkladu mám tabulku, která má jeden index a sekvenci s více než 100 MB dat.
postgres=# d+ cache
Table "public.cache"
Column | Type | Modifiers | Storage | Description
--------+---------+-----------------------------------------+----------+-------------
name | text | | extended |
code | integer | | plain |
id | integer | default nextval('icache_seq'::regclass) | plain |
Indexes:
"icache" btree (code)
Has OIDs: no
Dotaz, abyste zjistili velikost obsazenou tabulkou, sekvencí a jejím indexem.
postgres=# SELECT c.relname AS object_name,
CASE when c.relkind='r' then 'table'
when c.relkind='i' then 'index'
when c.relkind='S' then 'sequence'
else 'others'
END AS type,pg_relation_size(c.relname::text) AS size, pg_size_pretty(pg_relation_size(c.relname::text)) AS pretty_size
FROM pg_class c
JOIN pg_roles r ON r.oid = c.relowner
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE (c.relkind = ANY (ARRAY['r'::"char", 'i'::"char", 'S'::"char",''::"char"])) AND n.nspname = 'public';
object_name | type | size | pretty_size
-------------+----------+----------+-------------
icache_seq | sequence | 8192 | 8192 bytes
cache | table | 83492864 | 80 MB
icache | index | 35962880 | 34 MB
(3 rows)
Total object size 'cache'
postgres=# select pg_size_pretty(pg_total_relation_size('cache'));
pg_size_pretty
----------------
114 MB
(1 row)
Napsal jsem malý dotaz tím, že jsem spojil pgfincore a pg_buffercache, abych vytáhl informace z mezipaměti PG Buffer &OS Page. Tento dotaz budu používat ve svém příkladu, pouze vložím výstupy tohoto dotazu.
select rpad(c.relname,30,' ') as Object_Name,
case when c.relkind='r' then 'Table' when c.relkind='i' then 'Index' else 'Other' end as Object_Type,
rpad(count(*)::text,5,' ') as "PG_Buffer_Cache_usage(8KB)",
split_part(pgfincore(c.relname::text)::text,','::text,5) as "OS_Cache_usage(4KB)"
from pg_class c inner join pg_buffercache b on b.relfilenode=c.relfilenode
inner join pg_database d on (b.reldatabase=d.oid and d.datname=current_database() and c.relnamespace=(select oid from pg_namespace where nspname='public'))
group by c.relname,c.relkind
order by "PG_Buffer_Cache_usage(8KB)"
desc limit 10;
object_name | object_type | PG_Buffer_Cache_usage(8KB) | OS_Cache_usage(4KB)
-------------+-------------+----------------------------+---------------------
(0 rows)
Note: I have bounced the cluster to flush PG buffers & OS Page Cache. So, no data in any Cache/buffer.
Přednačtení vztahu/indexu pomocí pg_prewarm:
Před návratem klastru jsem provedl sekvenční skenování celé tabulky na tabulku „Cache“ a zaznamenal jsem čas, který je před zahřátím vztahu/indexu.
postgres=# explain analyze select * from cache ;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Seq Scan on cache (cost=0.00..26192.00 rows=1600000 width=19) (actual time=0.033..354.691 rows=1600000 loops=1)
Total runtime: 427.769 ms
(2 rows)
Umožňuje zahřát vztah/index/sekvenci pomocí pg_prewarm a zkontrolovat plán dotazů.
postgres=# select pg_prewarm('cache','main','buffer',null,null);
pg_prewarm
------------
10192
(1 row)
postgres=# select pg_prewarm('icache','main','buffer',null,null);
pg_prewarm
------------
4390
(1 row)
Output of combined buffers:
object_name | object_type | PG_Buffer_Cache_usage(8KB) | OS_Cache_usage(4KB)
-------------+-------------+----------------------------+---------------------
icache | Index | 4390 | 8780
cache | Table | 10192 | 20384
(2 rows)
Výstup pgfincore:
postgres=# select relname,split_part(pgfincore(c.relname::text)::text,','::text,5) as "In_OS_Cache" from pg_class c where relname ilike '%cache%';
relname | In_OS_Cache
------------+-------------
icache_seq | 2
cache | 20384
icache | 8780
(3 rows)
or for each object.
postgres=# select * from pgfincore('cache');
relpath | segment | os_page_size | rel_os_pages | pages_mem | group_mem | os_pages_free | databit
------------------+---------+--------------+--------------+-----------+-----------+---------------+---------
base/12780/16790 | 0 | 4096 | 20384 | 20384 | 1 | 316451 |
(1 row)
Chcete-li získat podobné informace pomocí skriptu python-ftools, musíte znát číslo relfilenode objektů, zkontrolujte níže.
postgres=# select relfilenode,relname from pg_class where relname ilike '%cache%';
relfilenode | relname
-------------+----------------
16787 | icache_seq /// you can exclude sequence.
16790 | cache /// table
16796 | icache /// index
(3 rows)
pomocí skriptu python-ftools
Není to zajímavé...!!!!.
Nyní porovnejte plán vysvětlení po zahřátí tabulky do vyrovnávací paměti.
postgres=# explain analyze select * from cache ;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Seq Scan on cache (cost=0.00..26192.00 rows=1600000 width=19) (actual time=0.016..141.804 rows=1600000 loops=1)
Total runtime: 215.100 ms
(2 rows)
Jak vyprázdnit/předem zahřát vztah/index v mezipaměti operačního systému?
Pomocí pgfadvise můžete předběžně načíst nebo vyprázdnit vztah z mezipaměti operačního systému. Pro více informací napište df pgfadvise* do terminálu pro všechny funkce související s pgfadvise. Níže je uveden příklad vyprázdnění mezipaměti operačního systému.
postgres=# select * from pgfadvise_dontneed('cache');
relpath | os_page_size | rel_os_pages | os_pages_free
------------------+--------------+--------------+---------------
base/12780/16790 | 4096 | 20384 | 178145
(1 row)
postgres=# select * from pgfadvise_dontneed('icache');
relpath | os_page_size | rel_os_pages | os_pages_free
------------------+--------------+--------------+---------------
base/12780/16796 | 4096 | 8780 | 187166
(1 row)
postgres=# select relname,split_part(pgfincore(c.relname::text)::text,','::text,5) as "In_OS_Cache" from pg_class c where relname ilike '%cache%';
relname | In_OS_Cache
------------+-------------
icache_seq | 0
cache | 0
icache | 0
(3 rows)
Zatímco tyto věci probíhají v jednom okně, můžete zkontrolovat poměr čtení/zápisu pomocí dstat. Pro více možností použijte dstat –list
dstat -s –top-io –top-bio –top-mem
Přednačítání rozsahu bloků pomocí funkce pg_prewarm range.
Předpokládejme, že z nějakého důvodu chcete odskočit cluster, ale jedna z velkých tabulek, která je ve vyrovnávací paměti, funguje dobře. Při bouncingu už vaše tabulka není v bufferech, abyste se dostali zpět do původního stavu, jak byl před bouncingem, pak musíte vědět, kolik bloků tabulky bylo v bufferech a předem je načíst pomocí možnosti pg_prewarm range.
Vytvořil jsem tabulku dotazem na pg_buffercache a později jsem odeslal informace o rozsahu bloku na pg_prewarm. Díky tomu jsou sdílené vyrovnávací paměti zpět s dříve načtenou tabulkou. Viz příklad.
select c.relname,count(*) as buffers from pg_class c
inner join pg_buffercache b on b.relfilenode=c.relfilenode and c.relname ilike '%cache%'
inner join pg_database d on (b.reldatabase=d.oid and d.datname=current_database())
group by c.relname
order by buffers desc;
relname | buffers
---------+---------
cache | 10192
icache | 4390
(2 rows)
Note: These are the blocks in buffer.
postgres=# create table blocks_in_buff (relation, fork, block) as select c.oid::regclass::text, case b.relforknumber when 0 then 'main' when 1 then 'fsm' when 2 then 'vm' end, b.relblocknumber from pg_buffercache b, pg_class c, pg_database d where b.relfilenode = c.relfilenode and b.reldatabase = d.oid and d.datname = current_database() and b.relforknumber in (0, 1, 2);
SELECT 14716
Odskočte cluster a předem načtěte rozsah bloků souvisejících s tabulkou do vyrovnávacích pamětí z „blocks_in_buff“.
postgres=# select sum(pg_prewarm(relation, fork, 'buffer', block, block)) from blocks_in_buff;
sum
-------
14716
(1 row)
postgres=# select c.relname,count(*) as buffers from pg_class c
inner join pg_buffercache b on b.relfilenode=c.relfilenode and c.relname ilike '%cache%'
inner join pg_database d on (b.reldatabase=d.oid and d.datname=current_database())
group by c.relname
order by buffers desc;
relname | buffers
---------+---------
cache | 10192
icache | 4390
(2 rows)
Vidíte, můj shared_buffer's je zpět ve hře.
Užívat si…!!! vrátí se s více zajímavými věcmi. Pište své komentáře.