PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Caching di PostgreSQL

Caching…!!, agak sulit untuk menjelaskan secara singkat dengan satu artikel. Tapi akan mencoba berbagi ilmu yang saya pelajari dari Heikki / Robert Haas / Bruce Momjian pendeknya. Di PostgreSQL, ada dua lapisan, buffer bersama PG dan cache Halaman OS, setiap baca/tulis harus melewati cache OS (Tidak ada bypass hingga sekarang). Postgres menulis data pada Cache Halaman OS dan mengonfirmasi kepada pengguna seperti yang telah ditulis ke disk, kemudian cache OS menulis ke disk fisik dengan kecepatannya sendiri. Buffer bersama PG tidak memiliki kendali atas OS Page Cache dan bahkan tidak tahu apa yang ada di cache OS. Jadi, sebagian besar rekomendasi yang diberikan oleh Postgres DBA/Professional untuk memiliki DISK yang lebih cepat/cache yang lebih baik.

Cache/buffer di PostgreSQL lebih kuat seperti database lain dan sangat canggih. Seperti saya dari latar belakang Oracle (pola pikir juga…:) ), jadi, pertanyaan saya dari siapa saya belajar adalah bagaimana/kapan/apa/mengapa dll., mengenai cache buffer Database, buffer yang disematkan, cache buffer database Flushing, preloading database dll., Saya mendapatkan semua jawaban saya dari mereka, namun pendekatannya sedikit berbeda. Meskipun pertanyaan saya mengganggu, mereka menjawab dengan sangat sabar dan mengklarifikasi saya dengan baik sehingga Anda membaca blog ini…. :)..

Pada beberapa pembelajaran (masih belajar), saya menggambar gambaran kecil tentang bagaimana aliran data antara Memori ke Disk di Postgres dan juga beberapa alat penting dan patch BARU oleh Robert Haas(pg_prewarm) .

pg_buffercache
Modul contrib, yang memberitahu apa yang ada di cache buffer PostgreSQL. Instalasi di bawah ini:-

postgres=# CREATE EXTENSION pg_buffercache;

pgfincore
Memiliki fungsi untuk memberikan informasi tentang data apa saja yang ada di OS Page Cache. Pgfincore, modul menjadi sangat berguna ketika dipukul dengan pg_buffercache, sekarang orang bisa mendapatkan cache buffer PG &informasi Cache Halaman OS bersama-sama. Terima kasih kepada Cerdic Villemain. Pgfincore, backbone adalah fadvise, fincore adalah ftools linux. Anda juga dapat menggunakan fincore/fadvise dengan menginstal source. Dua hal, Anda dapat menggunakan modul contrib pgfincore atau ftools keduanya hasilnya sama. Saya mencoba keduanya, mereka luar biasa.

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
Memuat terlebih dahulu relasi/indeks ke dalam cache buffer PG. Apakah mungkin di PostgreSQL? oh ya, Terima kasih kepada Robert Haas , yang baru saja mengirimkan patch ke komunitas, semoga tersedia di PG 9.2 atau PG 9.3. Namun, Anda dapat menggunakan tambalan untuk pengujian Anda di PG 9.1.

pg_prewarm memiliki tiga MODE:

  1. PREFETCH: Mengambil blok data secara asinkron ke dalam cache OS saja tidak ke buffer PG (hanya mengenai cache OS)
  2. BACA: Membaca semua blok ke buffer dummy dan memaksa ke cache OS. (hanya mengenai cache OS)
  3. BUFFER: membaca semua blok atau rentang blok ke cache buffer database.

Pemasangan:
Saya menerapkan tambalan pg_prewarm pada instalasi sumber PG saya, Anda perlu men-tweak sesuai pengaturan Anda.

  1. Untar lokasi sumber PG :/usr/local/src/postgresql-9.1.3
  2. Lokasi penginstalan PG :/usr/local/pgsql91
  3. Semua unduhan Lokasi :/usr/local/src

Catatan:Instal PG sebelum menerapkan pg_prewarm patch.

1. Unduh patch ke /usr/local/src/ location
http://archives.postgresql.org/pgsql-hackers/2012-03/binRVNreQMnK4.bin
Patch terlampir Email:
http://archives.postgresql.org/message-id/CA+TgmobRrRxCO+t6gcQrw_dJw+Uf9ZEdwf9beJnu+RB5TEBjEw@mail.gmail.com
2. Setelah mengunduh, buka lokasi sumber PG dan ikuti langkah-langkahnya.

# 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. Perintah di atas akan membuat file di bawah $PGPATH/contrib/extension. Sekarang Anda siap untuk menambahkan 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

status
Kombinasi alat vmstat,iostat,netstat,top,dll., bersama-sama dalam satu perintah linux "dstat". Ketika basis data berperilaku tidak biasa, untuk mengetahui penyebab dari level OS, kami membuka beberapa terminal untuk menarik proses, memori, baca/tulis disk, informasi jaringan, yang agak sulit untuk di-shuffle antar windows. Jadi, dstat memiliki opsi server di dalamnya, yang membantu menampilkan semua perintah dalam satu output satu jendela.

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/

Linux ftools
Dirancang untuk bekerja dengan panggilan sistem linux modern termasuk, mincore, fallocate, fadvise, dll. Ftools, akan membantu Anda mengetahui file apa yang ada di cache OS. Menggunakan skrip perl/python Anda dapat mengambil informasi cache halaman OS pada file objek (pg_class.relfilenode). pg_fincore didasarkan pada ini. Anda dapat menggunakan skrip pgfincore atau 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.

Sekarang, kita siap untuk melanjutkan dengan contoh untuk memeriksa dengan alat &utilitas. Dalam contoh saya, saya memiliki tabel, ia memiliki satu indeks &urutan dengan 100+ MB data di dalamnya.

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

Query untuk mengetahui ukuran tabel, urutan dan indeksnya.

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)

Saya telah menulis permintaan kecil dengan memukul pgfincore dan pg_buffercache untuk menarik informasi dari cache Halaman Buffer &OS PG. Saya akan menggunakan kueri ini melalui contoh saya, hanya menempelkan output kueri ini.

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.

Preloading relasi/indeks menggunakan pg_prewarm:
Sebelumnya, memantulkan cluster Saya telah menjalankan kueri pemindaian sekuensial tabel lengkap pada tabel "Cache", dan mencatat waktu sebelum menghangatkan relasi/indeks.

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)

Mari menghangatkan relasi/indeks/urutan menggunakan pg_prewarm dan memeriksa rencana kueri.

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)

keluaran 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)

Untuk mengambil informasi serupa menggunakan skrip python-ftools Anda perlu mengetahui nomor objek relfilenode, periksa di bawah.

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)

menggunakan skrip python-ftools

Menarik kan….!!!!.
Sekarang bandingkan rencana penjelasan setelah memanaskan meja ke dalam buffer.

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)

Bagaimana cara menyiram/menghangatkan relasi/indeks di cache OS?
Menggunakan pgfadvise, Anda dapat memuat atau menghapus relasi dari cache OS. Untuk informasi lebih lanjut, ketik df pgfadvise* di terminal untuk semua fungsi yang terkait dengan pgfadvise. Di bawah ini adalah contoh membersihkan cache OS.

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)

Sementara hal-hal ini terjadi dalam satu jendela, Anda dapat memeriksa rasio baca/tulis dengan menggunakan dstat. Untuk opsi lainnya, gunakan dstat –list
dstat -s –top-io –top-bio –top-mem

Preloading Rentang blok menggunakan fungsionalitas rentang pg_prewarm.
Asumsikan, karena alasan tertentu, Anda ingin memantulkan cluster, tetapi salah satu tabel besar yang ada di buffer berkinerja baik. Saat memantul, tabel Anda tidak lagi di buffer, untuk kembali ke keadaan semula seperti sebelum memantul maka Anda harus tahu berapa banyak blok tabel yang ada di buffer dan memuatnya terlebih dahulu menggunakan opsi rentang pg_prewarm.

Saya telah membuat tabel dengan menanyakan pg_buffercache dan kemudian saya telah mengirim informasi rentang blok ke pg_prewarm. Dengan ini, buffer bersama kembali dengan tabel yang dimuat sebelumnya di dalamnya. Lihat contohnya.

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

Pantulkan kluster dan muat terlebih dahulu rentang blok yang terkait dengan tabel ke dalam buffer dari “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)

Lihat, shared_buffer saya kembali dimainkan.

Menikmati…!!! akan kembali dengan hal-hal yang lebih menarik. Posting komentar Anda.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Query PostgreSQL dengan Npgsql dan Entity Framework menggunakan unaccent

  2. Menghubungkan ke Postgresql dalam wadah buruh pelabuhan dari luar

  3. Apakah kueri jenis SELECT satu-satunya jenis yang dapat disarangkan?

  4. Replikasi Londiste dengan PostgreSQL 9.0

  5. Postgres Tertanam untuk Tes Boot Musim Semi