PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Кеширане в PostgreSQL

Кеширане...!!, малко е трудно да се направи накратко с една статия. Но ще се опитам да споделя знанията си, научени от Хейки/Робърт Хаас/Брус Момджиан накратко. В PostgreSQL има два слоя, PG споделени буфери и кеш на OS Page, всяко четене/запис трябва да преминава през кеша на ОС (без байпас до сега). Postgres записва данни в OS Page Cache и потвърждава на потребителя, както е записал на диск, по-късно записва в кеша на ОС на физически диск със собствено темпо. Споделените буфери на PG нямат контрол върху кеша на страниците на ОС и дори не знаят какво има в кеша на ОС. Така че повечето от препоръките, дадени от Postgres DBA/Professional's, за по-бърз ДИСК/по-добър кеш.

Кешовете/буферите в PostgreSQL са по-силни като другите бази данни и са много сложни. Тъй като съм от фона на Oracle (също така… :) ), въпросът ми е от кого научих беше как/кога/какво/защо и т.н., по отношение на кеша на буфера на базата данни, фиксираните буфери, изчистването на кеша на буферите на базата данни, предварителното зареждане на базата данни и т.н., Получих всичките си отговори от тях, но подходът е малко по-различен. Въпреки че въпросите ми бяха досадни, те отговориха с голямо търпение и ме изясниха до голяма степен, в резултат на което четете този блог... :)..

Върху някои обучения (все още се уча) направих кратък преглед на това как се обменят данни между паметта към диска в Postgres, а също и някои от важните инструменти и НОВА корекция от Robert Haas(pg_prewarm) .

pg_buffercache
Модул contrib, който казва какво има в буферния кеш на PostgreSQL. Инсталация по-долу:-

postgres=# СЪЗДАВАНЕ НА РАЗШИРЕНИЕ pg_buffercache;

pgfincore
Има функционалност да дава информация за това какви данни са в кеша на страниците на ОС. Pgfincore, модулът става много удобен, когато се свърже с pg_buffercache, сега можете да получите PG буферен кеш и информация за кеша на страниците на ОС заедно. Благодаря на Cerdic Villemain. Pgfincore, backbone е fadvise, fincore, които са linux ftools. Можете също да използвате fincore/fadvise, като инсталирате източник. Две неща, можете да използвате pgfincore contrib modul или ftools и двата резултата са еднакви. Опитах и ​​двете, просто са страхотни.

Инсталация:
Изтеглете най-новата версия:http://pgfoundry.org/frs/download.php/3186/pgfincore-v1.1.1.tar.gz
Като root потребител:
export PATH=/usr/local/pgsql91/bin:$PATH //Задайте пътя до точка pg_config.
tar -xvf pgfincore-v1.1.1.tar.gz
cd pgfincore-1.1.1
направи чисто
направи
направи инсталиране

Сега се свържете с PG и изпълнете командата по-долу

postgres=# CREATE EXTENSION pgfincore;

pg_prewarm
Предварително зареждане на релацията/индекса в PG буферния кеш. Възможно ли е в PostgreSQL? о, да, благодарение на Робърт Хаас , който наскоро изпрати пач на общността, да се надяваме, че може да бъде наличен в PG 9.2 или PG 9.3. Въпреки това, можете да използвате корекцията за вашето тестване на PG 9.1.

pg_prewarm има три РЕЖИМА:

  1. ПРЕВАРИТЕЛНО ИЗВЛЕЧВАНЕ: Асинхронно извличане на блокове от данни в кеша на ОС, а не в PG буферите (само в кеша на ОС)
  2. Прочетете: Чете всички блокове в фиктивния буфер и принуждава в кеша на ОС. (улавя само кеша на ОС)
  3. БУФЕР: чете всички блокове или диапазон от блокове в кеша на буфера на базата данни.

Инсталация:
Прилагам pg_prewarm пач на моята инсталация на PG източник, трябва да настроите според настройката си.

  1. Отмяна на местоположението на източника на PG:/usr/local/src/postgresql-9.1.3
  2. Место за инсталиране на PG:/usr/local/pgsql91
  3. Местоположение на всички изтегляния:/usr/local/src

Забележка:Инсталирайте PG, преди да приложите pg_prewarm пач.

1. Изтеглете корекцията в /usr/local/src/ location
http://archives.postgresql.org/pgsql-hackers/2012-03/binRVNreQMnK4.bin
Прикачен корекция Имейл:
http://archives.postgresql.org/message-id/CA+TgmobRrRxCO+t6gcQrw_dJw+Uf9ZEdwf9beJnu+RB5TEBjEw@mail.gmail.com
2. След изтегляне отидете на местоположението на източника на PG и следвайте стъпките.

# cd /usr/local/src/postgresql-9.1.3
# patch -p1 <../pg_prewarm.bin (преименувах след изтегляне)
# make -C contrib/pg_prewarm
# make -C contrib/pg_prewarm install

3. Горната команда ще създаде файлове под $PGPATH/contrib/extension. Сега сте готови да добавите модула за принос.

postgres=# create EXTENSION pg_prewarm;
СЪЗДАВАНЕ НА РАЗШИРЕНИЕ
postgres=# dx
Списък на инсталираните разширения
Име | Версия | Схема | Описание
----------------+--------+-----------+----- ----------------------------------
pg_buffercache | 1.0 | обществено | прегледайте споделения буферен кеш
pg_prewarm | 1.0 | обществено | данни за предварителни отношения
pgfincore | 1.1.1 | обществено | преглед и управление на кеша на буфера на OS
plpgsql | 1.0 | pg_каталог | Процедурен език PL/pgSQL
(4 реда)

Документация:
/usr/local/src/postgresql-9.1.3/doc/src/sgml
[ root@localhost sgml]# ll pgpre*
-rw-r--r-- 1 root root 2481 10 апр 10:15 pgprewarm.sgml

dstat
Комбинация от vmstat,iostat,netstat,top и т.н., инструмент заедно в една linux команда “dstat”. Когато базата данни се държи необичайно, за да разберем причината от нивото на операционната система, ние отваряме няколко терминала за изтегляне на процес, памет, четене/запис на диск, мрежова информация, което е малко трудно да се разбърква между прозорците. И така, dstat има сървърни опции в него, което помага да се покажат всички команди в един изходен прозорец.

Инсталация:
Връзка за изтегляне на Dstat:(RHEL 6)
wget http://pkgs.repoforge.org/dstat/dstat-0.7.2-1.el6.rfx.noarch.rpm
или
yum install dstat
Документация:http://dag.wieers.com/home-made/dstat/

Linux ftools
Разработено е за работа с модерни системни извиквания на Linux, включително mincore, fallocate, fadvise и т.н. Ftools, ще ви помогне да разберете какви файлове са в кеша на ОС. Използвайки perl/python скриптове, можете да извлечете информация за кеша на страниците на ОС за обектни файлове (pg_class.relfilenode). pg_fincore се основава на това. Можете да използвате pgfincore или ftools скриптове.

Инсталиране:
Изтеглете tar.gz от връзката.
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

Забележка:Трябва да имате инсталирани python &psycopg2 преди инсталиране на python-ftools.

Сега сме готови да продължим с пример, за да проверим с инструментите и помощните програми. В моя пример имам таблица, тя има един индекс и последователност със 100+ MB данни в нея.

postgres=# d+ кеш
Таблица "public.cache"
Колона | Тип | Модификатори | Съхранение | Описание
-------+--------+------------------------------ ---------------+---------+------------
име | текст | | разширен |
код | цяло число | | обикновен |
id | цяло число | по подразбиране nextval('icache_seq'::regclass) | обикновен |
Индекси:
"icache" btree (код)
Има OID:не

Заявка, за да разберете размера, зает от таблица, последователност и нейния индекс.

postgres=# SELECT c.relname AS object_name,
CASE, когато c.relkind='r', след това 'table'
когато c.relkind='i' след това 'index'
когато c.relkind='S', тогава 'sequence'
друго 'others'
END AS тип,pg_relation_size(c.relname::text) AS размер, pg_size_pretty(pg_relation_size(c.relname::text) )) КАТО beautiful_size
ОТ pg_class c
СЪЕДИНЕТЕ се към pg_roles r ON r.oid =c.relowner
LEFT JOIN pg_namespace n ON n.oid =c.relnamespace
КЪДЕ (c. relkind =ANY (ARRAY['r'::"char", 'i'::"char", 'S'::"char",''::"char"])) И n.nspname ='public ';

име_на_обект | тип | размер | красив_размер
------------+----------+---------+--------- ----
icache_seq | последователност | 8192 | 8192 байта
кеш | таблица | 83492864 | 80 MB
cache | индекс | 35962880 | 34 MB
(3 реда)

Общ размер на обекта 'кеш'

postgres=# изберете pg_size_pretty(pg_total_relation_size('cache'));
pg_size_pretty
----------------
114 MB
(1 ред)

Написах малка заявка чрез clubbing pgfincore и pg_buffercache за изтегляне на информация от PG Buffer &OS Page кеша. Ще използвам тази заявка в моя пример, като поставям само резултатите от тази заявка.

изберете rpad(c.relname,30,' ') като Object_Name,
случай, когато c.relkind='r', след това 'Таблица', когато c.relkind='i', след това 'Index', друго 'Друго ' завършва като Object_Type,
rpad(count(*)::text,5,' ') като "PG_Buffer_Cache_usage(8KB)",
split_part(pgfincore(c.relname::text)::text ,','::text,5) като "OS_Cache_usage(4KB)"
от pg_class c вътрешно присъединяване pg_buffercache b на b.relfilenode=c.relfilenode
вътрешно присъединяване pg_database d на (b.reldatabase=d.oid и d.datname=current_database() и c.relnamespace=(изберете oid от pg_namespace, където nspname='public'))
група по c.relname,c.relkind
подреждане по "PG_Buffer_Cache_usage (8KB)"
ограничение за описване 10;

име_на_обект | тип_обект | PG_Buffer_Cache_usage(8KB) ​​| OS_Cache_usage(4KB)
------------+------------+-------------- --------------+---------------------
(0 реда)

Забележка:Отскочих клъстера, за да прочистя PG буферите и кеша на страниците на ОС. Така че няма данни в никакъв кеш/буфер.

Предварително зареждане на релация/индекс с помощта на pg_prewarm:
Преди отскачането на клъстера пуснах заявка за последователно сканиране на пълна таблица в таблицата „Кеш“ и отбелязах времето, което е преди затопляне на релацията/индекса.

postgres=# обяснете анализирайте изберете * от кеша;
ПЛАН НА ЗАЯВКАТА
-------------------------- -------------------------------------------------- -------------------------------------
Последователно сканиране в кеша (цена=0,00. .26192,00 реда=1600000 ширина=19) (действително време=0,033..354,691 реда=1600000 цикъла=1)
Общо време на изпълнение:427,769 мс
(2 реда преди)
Позволява затопляне на релация/индекс/последователност с помощта на pg_prewarm и проверка на плана на заявката.

postgres=# изберете pg_prewarm('cache','main','buffer',null,null);
pg_prewarm
-----------
10192
(1 ред)
postgres=# изберете pg_prewarm('icache','main','buffer',null,null);
pg_prewarm
---- --------
4390
(1 ред)

Изход на комбинирани буфери:
име_обект | тип_обект | PG_Buffer_Cache_usage(8KB) ​​| OS_Cache_usage(4KB)
------------+------------+-------------- --------------+---------------------
cache | Индекс | 4390 | 8780
кеш | Таблица | 10192 | 20384
(2 реда)

pgfincore изход:

postgres=# изберете relname,split_part(pgfincore(c.relname::text)::text,','::text,5) като "In_OS_Cache" от pg_class c, където relname или като '%cache%';
rename | In_OS_Cache
------------+------------
icache_seq | 2
кеш | 20384
cache | 8780
(3 реда)

или за всеки обект.

postgres=# изберете * от pgfincore('cache');
relpath | сегмент | os_page_size | rel_os_pages | pages_mem | group_mem | os_pages_free | databit
-----------------+--------+--------------+- -------------+-----------+-----------+------------ ---+--------
база/12780/16790 | 0 | 4096 | 20384 | 20384 | 1 | 316451 |
(1 ред)

За да извлечете подобна информация с помощта на скрипт на python-ftools, трябва да знаете номера на relfilenode на обектите, проверете по-долу.

postgres=# изберете relfilenode,relname от pg_class където relname или като '%cache%';
relfilenode | relname
------------+----------------
16787 | icache_seq /// можете да изключите последователността.
16790 | кеш /// таблица
16796 | icache /// индекс
(3 реда)

използвайки скрипт на python-ftools

Не е ли интересно...!!!!.
Сега сравнете плана за обяснение след затопляне на таблицата в буфер.

postgres=# обяснете анализирайте изберете * от кеша;
ПЛАН НА ЗАЯВКАТА
-------------------------- -------------------------------------------------- -------------------------------------
Последователно сканиране в кеша (цена=0,00. .26192,00 реда=1600000 ширина=19) (действително време=0,016..141,804 реда=1600000 цикъла=1)
Общо време на изпълнение:215,100 мс
(2 реда преди)
Как да изчистя/предварително загрявам релация/индексиране в кеша на ОС?
С помощта на pgfadvise можете да заредите предварително или да изчистите връзката от кеша на ОС. За повече информация въведете df pgfadvise* в терминал за всички функции, свързани с pgfadvise. По-долу е даден пример за прочистване на кеша на ОС.

postgres=# изберете * от pgfadvise_dontneed('cache');
relpath | os_page_size | rel_os_pages | os_pages_free
-----------------+--------------+----------- ---+--------------
base/12780/16790 | 4096 | 20384 | 178145
(1 ред)
postgres=# изберете * от pgfadvise_dontneed('icache');
relpath | os_page_size | rel_os_pages | os_pages_free
-----------------+--------------+----------- ---+--------------
base/12780/16796 | 4096 | 8780 | 187166
(1 ред)
postgres=# изберете relname,split_part(pgfincore(c.relname::text)::text,','::text,5) като "In_OS_Cache" от pg_class c където relname ilike '%cache%';
relname | In_OS_Cache
------------+------------
icache_seq | 0
кеш | 0
cache | 0
(3 реда)

Докато тези неща се случват в един прозорец, можете да проверите съотношението четене/запис с помощта на dstat. За повече опции използвайте dstat –list
dstat -s –top-io –top-bio –top-mem

Предварително зареждане на диапазон на блокове с помощта на функционалност pg_prewarm range.
Да приемем, че поради някаква причина искате да отскочите клъстера, но една голяма маса, която е в буфер, се представя добре. При отскачане масата ви вече не е в буфери, за да се върнете в първоначалното състояние, както е било преди отскачането, тогава трябва да знаете колко блока на таблицата са били в буферите и да ги заредите предварително, като използвате опцията pg_prewarm range.

Създадох таблица чрез запитване към pg_buffercache и по-късно изпратих информация за блоковата гама до pg_prewarm. По този начин споделените буфери се връщат с таблицата, заредена по-рано в нея. Вижте примера.

изберете c.relname,count(*) като буфери от pg_class c 
вътрешно присъединяване pg_buffercache b на b.relfilenode=c.relfilenode и c.relname ilike '%cache%'
вътрешно присъединяване pg_database d on (b.reldatabase=d.oid и d.datname=current_database())
група по c.relname
подреждане по буфери desc;
relname | буфери
--------+--------
кеш | 10192
cache | 4390
(2 реда)
Забележка:Това са блоковете в буфера.

postgres=# създайте таблица blocks_in_buff (релация, разклонение, блок) като изберете c.oid::regclass::text, case b.relforknumber, когато е 0, след това 'main', когато 1, след това 'fsm', когато 2 след това 'vm' край, b.relblocknumber от pg_buffercache b, pg_class c, pg_database d, където b.relfilenode =c.relfilenode и b.reldatabase =d.oid и d.datname =current_database() и b.relforknumber в (0, 1, 2);
SELECT 14716

Отклонете клъстера и предварително заредете диапазона от блокове, свързани с таблицата, в буфери от „blocks_in_buff“.

postgres=# изберете sum(pg_prewarm(relation, fork, 'buffer', block, block)) от blocks_in_buff;
sum
-------
14716
(1 ред)

postgres=# изберете c.relname,count(*) като буфери от pg_class c
вътрешно присъединяване pg_buffercache b на b.relfilenode=c.relfilenode и c. relname ilike '%cache%'
вътрешно присъединяване pg_database d на (b.reldatabase=d.oid и d.datname=current_database())
група по c.relname
подреждане по буфери desc;
рел име | буфери
--------+--------
кеш | 10192
cache | 4390
(2 реда)

Вижте, моят shared_buffer's се завърна в игра.

Наслади се…!!! ще се върна с още интересни неща. Публикувайте вашите коментари.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Бройте дните между 2 дати в JPA

  2. Не може просто да се използва името на таблицата PostgreSQL (връзка не съществува)

  3. Разгръщане на клъстер в множество облаци на PostgreSQL

  4. Проверете дали съществува стойност в масива на Postgres

  5. Връщане на редове, съответстващи на елементи от входния масив във функцията plpgsql