Сайт о телевидении

Сайт о телевидении

» » Комментариев нет. БД — большой кэш

Комментариев нет. БД — большой кэш

Я обещал написать о том, что в проектах с более менее серьезной нагрузкой БД либо помещается в память, либо не работает. Ситуация в современном мире меняется в связи с появлением SSD дисков, но пока что они стоят достаточно дорого, по сравнению со старыми добрыми вращающимися дисками. Чтобы «потрогать» это руками, проделаем несложный тест.

Я завел новую машину с Ubuntu 12.04, на облачном хостинге Amazon размера t1.micro. После этого необходимо поставить 2 пакета: postgresql-contrib-9.1 и ruby.

PostgreSQL contrib содержит, помимо всего прочего, программу pgbench, специально предназначенную для нагрузочного тестирования PostgreSQL.

В postgresql.conf параметр shared_buffers был выставлен в 64MB.

File . open ("res.txt" , "w" ) do | f | (1 .. 50 ). each do | s | # -i означает, что мы создаем чистую БД # -s - это scale factor, определяет размер БД `/usr/lib/postgresql/9.1/bin/pgbench -i -s #{ s } ` # -S - тесты для запросов только на чтение # -T 20 - тест длится 20 секунд # -c 40 - 40 клиентов # -j 4 - 4 потока res = `/usr/lib/postgresql/9.1/bin/pgbench -c 40 -j 4 -S -T 20` puts res f . write res end end

На машинках t1.micro free -m выдает следующее: total used free shared buffers cached Mem: 590 583 6 0 1 428

Именно этим обусловлен такой выбор границ scale factor. Про scale factor = 50 размер БД приблизительно 750Мб, то есть больше количества доступной памяти, а граница shared_buffers пересекается при значениях scale factor 4-5.

Давайте же посмотрим на график.

Данные получились не очень красивыми, но в целом - понятными. Виден провал в районе scale factor 5, а следующий провал в районе scale factor 45. Собственно, две явные ступеньки - выпадание из shared buffers и из дискового кэша.

16 фев 2015

Оптимизация работы PostgreSQL

by Admin

Настройка конфигурации

Настройка ресурсов

shared_buffers

Размер разделяемой между процессами PostgreSQL памяти, которая нужна для выполнения активных операций. Не следует указывать слишком большой объём, так как PostgreSQL использует также дисковый кэш.
Значения:
- Средний объём данных и 256-512 МБ доступной памяти: 16-32 МБ
- Большой объём данных и 1-4 ГБ доступной памяти: 64-256 МБ

temp_buffers
Буфер под временные объекты, в основном для временных таблиц.
Можно установить порядка 16 МБ

max_prepared_transactions
Количество одновременно подготавливаемых транзакций.
Для работы 1С этот параметр значения не имеет, PREPARE TRANSACTION там не используются.
Можно оставить по дефолту - 5

work_mem
Специальная память, используется для сортировки и кэширования таблиц, для одного запроса.
При задании этого параметра следует учитывать количество конкурентных запросов, выполняемых в один момент времени.
При памяти 1-4Gb рекомендуется устанавливать 32-128MB

maintenance_work_mem
Память использующаяся для операций VACUUM, CREATE INDEX, ALTER TABLE и FOREGIN KEY.
Следует устанавливать большее значение, чем для work_mem. Слишком большие значения приведут к использованию свопа.
При памяти 1-4Gb рекомендуется устанавливать 128-512MB

max_stack_depth
Специальный стек для сервера, в идеале он должен совпадать с размером стека, выставленном в ядре ОС. Установка большего значения, чем в ядре, может привести к ошибкам.
Рекомендуется устанавливать 2-4MB

max_fsm_relations
Максимальное количество таблиц, для которых будет отслеживаться свободное место в общей карте свободного пространства. Эти данные собираются VACUUM.
Выставьте параметр в соответствии с количеством таблиц в вашей базе с запасом. (Применимо для версий до 8.4)

max_fsm_pages
Количество блоков, для которых будет хранится информация о свободном месте. Информация хранится в разделяемой памяти, для каждой записи требуется по 6 байт.
Использование этого параметра позволяет избежать использования VACUUM FULL для базы, достаточно будет VACUUM. (Применимо для версий до 8.4)
Этот параметр должен быть не меньше чем 16*max_fsm_relations
Данный параметр задается автоматически при создании базы утилитой initdb
Можно задать его и вручную: в качестве начального приближения можно взять половину от среднего количества записей, изменяемых (UPDATE или DELETE) между запусками команды VACUUM.
Оценить это значение (база должна проработать уже какое-то время) можно выполнив:

vacuum full analyze;
NOTICE: number of page slots needed (196272) exceeds max_fsm_pages (153600)
HINT: Consider increasing the configuration parameter "max_fsm_pages" to a value over 196272.

max_files_per_process
Максимальное количество файлов, открываемых процессом и его подпроцессами в один момент времени.
Уменьшите данный параметр, если в процессе работы наблюдается сообщение "Too many open files ".

Запись транзакционных логов на диск

commit_delay и commit_siblings
Значение commit_delay выражается в микросекундах (0 по умолчанию). Значение commit_siblings выражается в штуках (5 по умолчанию).
commit_delay определяют задержку между попаданием записи в буфер журнала транзакций и сбросом её на диск. Если при успешном завершении транзакции активно не менее commit_siblings транзакций, то запись будет задержана на время commit_delay. Если за это время завершится другая транзакция, то их изменения будут сброшены на диск вместе, при помощи одного системного вызова. Эти параметры позволят ускорить работу, если параллельно выполняется много «мелких» транзакций.

fsync
Данный параметр отвечает за сброс данных из кэша на диск при завершении транзакций.
Если установить его значение

fsync=off

то данные не будут записываться на дисковые накопители сразу после завершения операций. Это может существенно повысить скорость операций insert и update, но есть риск повредить базу, если произойдет сбой (неожиданное отключение питания, сбой ОС, сбой дисковой подсистемы).
Используйте эту возможность только если у вас имеются надежные ИБП и программное обеспечение, завершающее работу системы при низком заряде батарей.
Не следует отключать fsync при работе PostgreSQL на Windows платформе, из-за нестабильности системы.

wal_sync_method
Метод, который используется для принудительной записи данных на диск.
Если fsync=off, то этот параметр не используется.

Возможные значения:
open_datasync - запись данных методом open() с параметром O_DSYNC
fdatasync - вызов метода fdatasync() после каждого commit
fsync_writethrough - вызывать fsync() после каждого commit игнорирую паралельные процессы
fsync - вызов fsync() после каждого commit
open_sync - запись данных методом open() с параметром O_SYNC

Не все методы доступны на определенных платформах. По умолчанию устанавливается первый, который доступен в системе.

full_page_writes
Установите данный параметр в off, если fsync=off.
Иначе

Когда этот параметр on, PostgreSQL записывает содержимое каждой страницы в журнал транзакций во время первой модификации таблицы после контрольной точки. Это необходимо потому что страницы могут записаться лишь частично если в ходе процесса ОС "упала". Это приволит к тому, что на диске оказаываются новые данные смешанные со старыми. Строкового уровня записи в журнал транзакций может быть не достаточно, что бы полность восстановить данные после "падения". full_page_writes гарантирует корректное восстановление, ценой увелечения записываемых данных в журнал транзакций.(Потому что журнал транзакций все время начинается с контрольной точки. Единственный способ снижения объема записи заключается в увеличении checkpoint interval).

wal_buffers
Количество памяти используемое в SHARED MEMORY для ведения транзакционных логов.
При доступной памяти 1-4GB рекомендуется устанавливать 256-1024kb

Оптимизация запросов

enable_nestloop
Определяет использование планировщика запросов. В некоторых случаях выключение планировщика может уменьшать время исполнения отдельных запросов, в том числе и значительно. Однако в подавляющем большинстве случаев планировщик позволяет уменьшить время выполнения запросов. Не следует его выключать, по крайней мере на постоянной основе.

random_page_cost
Устанавливает у планировщика оценку "стоимоти" не последовательного перебора данных. По умолчанию 4.0. Уменьшение этого значения по отношению к seq_page_cost вызовет у планировщика предпочтение сканирования индекса, увеличение -- наобород сделает сканирование индекса "дороже". Вы можете изменить оба значения чтобы изменить отношение "стоимости" дисковых операций ввода/выдода, по отношениб с "стоимости" использования процессора, которая бадет описана следующими параметрами.

На серверах с быстрыми дисковыми массивами имеет смысл уменьшать изначальную настройку до 3.0, 2.5 или даже до 2.0. Если же активная часть вашей базы данных много больше размеров оперативной памяти, попробуйте поднять значение параметра. Можно подойти к выбору оптимального значения и со стороны производительности запросов. Если планировщик запросов чаще, чем необходимо, предпочитает последовательные просмотры (sequential scans) просмотрам с использованием индекса (index scans), понижайте значение. И наоборот, если планировщик выбирает просмотр по медленному индексу, когда не должен этого делать, настройку имеет смысл увеличить. После изменения тщательно тестируйте результаты на максимально широком наборе запросов. Никогда не опускайте значение random_page_cost ниже 2.0; если вам кажется, что random_page_cost нужно еще понижать, разумнее в этом случае менять настройки статистики планировщика.

cpu_tuple_cost
Устанавливает у планировщика оценку "стоимоти" затрат на обработку каждой строки во время выполнения запроса. По умолчанию 0,01.

cpu_index_tuple_cost
Устанавливает у планировщика оценку "стоимоти" затрат на обработку каждого индекса во время операции сканирования индекса. По умолчанию 0,005

cpu_operator_cost
Устанавливает у планировщика оценку "стоимоти" затрат на выполнение каждого оператора или функции во время выполнения запроса. По умолчанию 0.0025.

effective_cache_size
Передает данные планировщику запросов об объёме памяти, которая используется ОС для кэширования файлов, для одного запроса.
Этот параметр в ОС можно посмотреть в настройках:
Для Windows: в Диспетчере задач, Закладка Быстродействие, Физическая память-Системный кэш.
Для Linux: наберите команду free, необходимое значение в столбце cached (в kB)

Данное значение необходимо разделить на количество конкурентных запросов в один момент времени (среднее количество подключений к базе + запас).

default_statistics_target
Устанавливает глубину статистики по таблицам. БОльшие значения могут повысить время выполнения команды ANALYZE, но улучшат построение плана запроса.
Рекомендуется устанавливать порядка 100.

constraint_exclusion
Включает или отключает использование планером ограничений CONSTRAINT в таблицах при построении запросов.
Рекомендуется установить значение on, при этом, если Вы изменяете CONSTRAINT у таблиц, необходимо обновить их статистику выполнив ANALYZE, в противном случае будут построены неверные планы запросов.

Сбор статистики

stats_command_string
Передавать ли сборщику статистики информацию о текущей выполняемой команде и времени начала её выполнения.
Устанавливать on

stats_start_collector
Включать ли сбор статистики.
Устанавливать on

stats_row_level, stats_block_level
Собирать ли информацию об активности на уровне записей и блоков соответственно.
Устанавливать
stats_row_level=on
stats_block_level=off

stats_reset_on_server_start
Обнулять ли статистику при перезапуске сервера
Устанавливать off

Автовакуум

VACUUM - сборка "мусора". VACUUM восстанавливает место занятые "мертвыми" данными. При выполнении обычных операций с данными, PostgreSQL не удаляет данные физически из таблиц, это происходит с операцией VACUUM.

autovacuum
Включать ли автовакуум (автоматического запуска VACUUM),
устанавливать on

autovacuum_naptime
Пауза между запусками Автовакуума.
Зависит от того, как часто обновляются данные в ваших таблицах. Может соствлять порядка 5min, по умолчанию 1min

autovacuum_analyze_threshold
Определяет минимальное количество вставок, обновлений или удалений необходимых для посылки сигнала на запуск ANALYZE в любой таблице. Этот параметр может быть изменен для отдельных таблиц путем изменения параметров хранения.

autovacuum_vacuum_threshold
Определяет минимальное количество вставок, обновлений или удалений необходимых для посылки сигнала на запуск VACUUM в любой таблице. Этот параметр может быть изменен для отдельных таблиц путем изменения параметров хранения.

Блокировки

max_locks_per_transaction
Количество блокировок за одну транзакцию:
установить порядка 250

deadlock_timeout
Время жизни взаимных блокировок.
Установить порядка 2 секунд.

Возможная ошибка
После исправления файла конфигурации PostgreSQL может не запуститься, выдав ошибку:

FATAL: could not create shared memory segment:...
Failed system call was shmget(key=5432001, size=140075008, 03600).
This error usually means that PostgreSQL"s request for a shared memory segment exceeded your kernel"s SHMMAX parameter. You can either reduce the request size or reconfigure the kernel with larger SHMMAX. To reduce the request size (currently 140075008 bytes), reduce PostgreSQL"s shared_buffers parameter (currently 16384) and/or its max_connections parameter (currently 10).
If the request size is already small, it"s possible that it is less than your kernel"s SHMMIN parameter, in which case raising the request size or reconfiguring SHMMIN is called for.
The PostgreSQL documentation contains more information about shared memory configuration.

Для исправления необходимо увеличить параметр SHMMAX в системе. Сделать это можно следующим образом (для ОС Linux):

Выполните команду:

echo 150829120 > /proc/sys/kernel/shmmax

указав свое новое значение для параметра (какое именно - можно посмотреть в логе ошибки PostgreSQL). Данная операция устанавливает параметр на лету, но после перезагрузки системы изменения будут потеряны. Чтобы этого не происходило, внесите в файл /etc/sysctl.conf следующую строку:

kernel.shmmax = 150829120

указав своё значение.

Пример конфигурации для сервера с 2G оперативной памяти

Средняя настройка

Среднестатическая настройка для максимальной производительности. Возможно для конкретного случая лучше подойдут другие настройки. Внимательно изучите данное руководство и настройте PostgreSQL, опираясь на эту информацию.

RAM -- размер памяти

* shared_buffers = 1/8 RAM или больше (но не более 1/4);
* work_mem в 1/20 RAM;
* maintenance_work_mem в 1/4;
* max_fsm_relations в планируемое кол-во таблиц в базах * 1.5;
* max_fsm_pages в max_fsm_relations * 2000;
* fsync = true;
* wal_sync_method = fdatasync;
* commit_delay = от 10 до 100 ;
* commit_siblings = от 5 до 10;
* effective_cache_size = 0.9 от значения cached, которое показывает free;
* random_page_cost = 2 для быстрых cpu, 4 для медленных;
* cpu_tuple_cost = 0.001 для быстрых cpu, 0.01 для медленных;
* cpu_index_tuple_cost = 0.0005 для быстрых cpu, 0.005 для медленных;
* autovacuum = on
* autovacuum_vacuum_threshold = 1800
* autovacuum_analyze_threshold = 900

Обслуживание базы

При первом запуске базы, после заливки данных, необходимо сделать ANALYZE для всей базы.

VACUUM выполняется автоматически, в соответствии с настройками в файле конфигурации.

VACUUM FULL выполнять не обязательно при правильно настроенном автовакууме.

Диски и файловые системы

Если в вашем сервере есть несколько физических дисков, то вы можете разнести файлы базы данных и журнал транзакций по разным дискам:

Остановите сервер.
Перенесите каталоги pg_clog и pg_xlog, находящийся в каталоге с базами данных, на другой диск.
Создайте на старом месте символическую ссылку.
Запустите сервер.

На данный момент производительность PostgreSQL в связке с сервером 1С:Предприятия в сравнении с тем же MS SQL оставляет желать лучшего. Эта статья продолжение попыток добиться достойной производительности на PostgreSQL. Хотя на данный момент у меня не получилось добиться производительности сопоставимой MS SQL, но думаю в недалеком будущем эта проблема будет решена.

Основные параметры PostgreSQL.

shared_buffers

Объём совместно используемой памяти, выделяемой PostgreSQL для кэширования данных, определяется числом страниц shared_buffers по 8 килобайт каждая. Следует учитывать, что операционная система сама кэширует данные, поэтому нет необходимости отводить под кэш всю наличную оперативную память. Размер shared_buffers зависит от многих факторов, для начала можно принять следующие значения:

  • 8–16 Мб – Обычный настольный компьютер с 512 Мб и небольшой базой данных,
  • 80–160 Мб – Небольшой сервер, предназначенный для обслуживания базы данных с объёмом оперативной памяти 1 Гб и базой данных около 10 Гб,
  • 400 Мб – Сервер с несколькими процессорами, с объёмом памяти в 8 Гб и базой данных занимающей свыше 100 Гб обслуживающий несколько сотен активных соединений одновременно.

work_mem

Под каждый запрос выделяется ограниченный объём памяти. Этот объём используется для сортировки, объединения и других подобных операций. При превышении этого объёма сервер начинает использовать временные файлы на диске, что может существенно снизить производительность. Оценить необходимое значение для work_mem можно разделив объём доступной памяти (физическая память минус объём занятый под другие программы и под совместно используемые страницы shared_buffers) на максимальное число одновременно используемых активных соединений.

maintenance_work_mem

Эта память используется для выполнения операций по сбору статистики ANALYZE , сборке мусора VACUUM , создания индексов CREATE INDEX и добавления внешних ключей. Размер памяти выделяемой под эти операции должен быть сравним с физическим размером самого большого индекса на диске.

effective_cache_size

PostgreSQL в своих планах опирается на кэширование файлов, осуществляемое операционной системой. Этот параметр соответствует максимальному размеру объекта, который может поместиться в системный кэш. Это значение используется только для оценки. effective_cache_size можно установить в ½ - 2/3 от объёма имеющейся в наличии оперативной памяти, если вся она отдана в распоряжение PostgreSQL.

ВНИМАНИЕ! Следующие параметры могут существенно увеличить производительность работы PostgreSQL. Однако их рекомендуется использовать только если имеются надежные ИБП и программное обеспечение, завершающее работу системы при низком заряде батарей.

fsync

Данный параметр отвечает за сброс данных из кэша на диск при завершении транзакций. Если установить в этом параметре значение off , то данные не будут записываться на дисковые накопители сразу после завершения операций. Это может существенно повысить скорость операций insert и update , но есть риск повредить базу, если произойдет сбой (неожиданное отключение питания, сбой ОС, сбой дисковой подсистемы).

Отрицательное влияние включенного fsync можно уменьшить отключив его и положившись на надежность вашего оборудования. Или правильно подобрав параметр wal_sync_method - метод, который используется для принудительной записи данных на диск.

Возможные значения:

  • open_datasync – запись данных методом open() с параметром O_DSYNC ,
  • fdatasync – вызов метода fdatasync() после каждого commit ,
  • fsync_writethrough – вызывать fsync() после каждого commit игнорирую параллельные процессы,
  • fsync – вызов fsync() после каждого commit ,
  • open_sync – запись данных методом open() с параметром O_SYNC .

ПРИМЕЧАНИЕ! Не все методы доступны на определенных платформах. Выбор метода зависит от операционной системы под управлением, которой работает PostgreSQL.

В состав PostgreSQL входит утилита pg_test_fsync , с помощью которой можно определить оптимальное значение параметра wal_sync_method .

Она выполняет серию дисковых тестов с использованием различных методов синхронизации. В результате этого теста получаются оценки производительности дисковой системы, по которым можно определить оптимальный метод синхронизации для данной операционной системы.

Я решил провести вышеуказанный тест на своем рабочем компьютере, имеющем следующие характеристики:

  • CPU: Intel Core i3-3220 @ 3.30GHz x 2
  • RAM: 4GB
  • HDD: Seagate ST3320418AS 320GB

Тест на Windows:

  • ОС: Windows 7 Максимальная x64
  • ФС: NTFS
  • СУБД: PostgreSQL 9.4.2-1.1C x64
C:\PROGRA~1\POSTGR~1\9.4.2-1.1C\bin>pg_test_fsync 5 seconds per test is Linux"s default) open_datasync 48817.440 ops/sec 20 usecs/op fdatasync n/a fsync 79.688 ops/sec 12549 usecs/op fsync_writethrough 80.072 ops/sec 12489 usecs/op open_sync n/a (in wal_sync_method preference order, except fdatasync is Linux"s default) open_datasync 24713.634 ops/sec 40 usecs/op fdatasync n/a fsync 78.690 ops/sec 12708 usecs/op fsync_writethrough 79.073 ops/sec 12646 usecs/op open_sync n/a 1 * 16kB open_sync write n/a 2 * 8kB open_sync writes n/a 4 * 4kB open_sync writes n/a 8 * 2kB open_sync writes n/a 16 * 1kB open_sync writes n/a on a different descriptor.) write, fsync, close 76.493 ops/sec 13073 usecs/op write, close, fsync 77.676 ops/sec 12874 usecs/op Non-Sync"ed 8kB writes: write 1800.319 ops/sec 555 usecs/op

По результатам теста мы видим, что для Windows оптимальным решением будет использование open_datasync .

Тест на Linux:

  • ОС: Debian 8.6 Jessie
  • Ядро: x86_64 Linux 3.16.0-4-amd64
  • ФС: ext4
  • СУБД: PostgreSQL 9.4.2-1.1C amd64
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 /usr/lib/postgresql/9.4/bin# ./pg_test_fsync 5 seconds per test O_DIRECT supported on this platform for open_datasync and open_sync. Compare file sync methods using one 8kB write: (in wal_sync_method preference order, except fdatasync is Linux"s default) open_datasync 80.215 ops/sec 12467 usecs/op fdatasync 80.349 ops/sec 12446 usecs/op fsync 39.384 ops/sec 25391 usecs/op fsync_writethrough n/a open_sync 40.013 ops/sec 24992 usecs/op Compare file sync methods using two 8kB writes: (in wal_sync_method preference order, except fdatasync is Linux"s default) open_datasync 40.033 ops/sec 24980 usecs/op fdatasync 77.264 ops/sec 12943 usecs/op fsync 36.325 ops/sec 27529 usecs/op fsync_writethrough n/a open_sync 19.659 ops/sec 50866 usecs/op Compare open_sync with different write sizes: (This is designed to compare the cost of writing 16kB in different write open_sync sizes.) 1 * 16kB open_sync write 38.697 ops/sec 25842 usecs/op 2 * 8kB open_sync writes 17.356 ops/sec 57616 usecs/op 4 * 4kB open_sync writes 8.996 ops/sec 111156 usecs/op 8 * 2kB open_sync writes 4.552 ops/sec 219686 usecs/op 16 * 1kB open_sync writes 2.218 ops/sec 450930 usecs/op Test if fsync on non-write file descriptor is honored: (If the times are similar, fsync() can sync data written on a different descriptor.) write, fsync, close 34.341 ops/sec 29120 usecs/op write, close, fsync 35.753 ops/sec 27970 usecs/op Non-Sync"ed 8kB writes: write 484193.516 ops/sec 2 usecs/op

По результатам теста мы видим, что наилучшую скорость выдают методы fdatasync и open_datasync . Так же можно заметить, что на же оборудовании Linux выдал скорость записи почти в половину больше, чем на Windows.

Следует учитывать, что в данных тестах использовалась дисковая система, состоящая из одного диска. При использовании RAID массива с большим количеством дисков картина может быть другой.

wal_buffers

Количество памяти используемое в SHARED MEMORY для ведения транзакционных логов. При доступной памяти 1-4 Гб рекомендуется устанавливать 256-1024 Кб. Этот параметр стоит увеличивать в системах с большим количеством модификаций таблиц базы данных.

checkpoint_segments

Oпределяет количество сегментов (каждый по 16 МБ) лога транзакций между контрольными точками. Для баз данных с множеством модифицирующих данные транзакций рекомендуется увеличение этого параметра. Критерием достаточности количества сегментов является отсутствие в логе предупреждений (warning) о том, что контрольные точки происходят слишком часто.

full_page_writes

Включение этого параметра гарантирует корректное восстановление, ценой увеличения записываемых данных в журнал транзакций. Отключение этого параметра ускоряет работу, но может привести к повреждению базы данных в случае системного сбоя или отключения питания.

synchronous_commit

Включает/выключает синхронную запись в лог-файлы после каждой транзакции. Включение синхронной записи защищает от возможной потери данных. Но, накладывает ограничение на пропускную способность сервера. Вы можете отключить синхронную запись, если вам необходимо обеспечить более высокую производительность по количеству транзакций. А потенциально низкая возможность потери небольшого количества изменений при крахе системы не критична. Для отключения синхронной записи установите значение off в этом параметре.

Еще одним способом увеличения производительности работы PostgreSQL является перенос журнала транзакций (pg_xlog) на другой диск. Выделение для журнала транзакций отдельного дискового ресурса позволяет получить получить при этом существенный выигрыш в производительности 10%-12% для нагруженных OLTP систем.

В Linux это делается с помощью создания символьной ссылки на новое положение каталога с журналом транзакций.

В Windows можно использовать для этих целей утилиту Junction . Для этого надо:

  1. Остановить PostgreSQL.
  2. Сделать бэкап C:\Program Files\PostgreSQL\X.X.X\data\pg_xlog .
  3. Скопировать C:\Program Files\PostgreSQL\X.X.X\data\pg_xlog в D:\pg_xlog и удалить C:\Program Files\PostgreSQL\X.X.X\data\pg_xlog .
  4. Распаковать программу Junction в C:\Program Files\PostgreSQL\X.X.X\data .
  5. Открыть окно CMD , перейти в C:\Program Files\PostgreSQL\X.X.X\data и выполнить junction -s pg_xlog D:\pg_xlog .
  6. Установить права на папку D:\pg_xlog пользователю postgres.
  7. Запустить PostgreSQL.
    Где X.X.X - версия используемой PostgreSQL.

Особенности и ограничения в 1С:Предприятие при работе с PostgreSQL.

Использование конструкции ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ.

В СУБД PostgreSQL реализована только частичная поддержка FULL OUTER JOIN (ERROR: “FULL JOIN is only supported with mergejoinable join conditions”). Для реализации полной поддержки FULL OUTER JOIN при работе 1С:Предприятия 8 с PostgreSQL подобный запрос трансформируется в другую форму с эквивалентным результатом, однако эффективность использования конструкции ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ снижается.

Оптимизация использования виртуальной таблицы СрезПоследних при работе с PostgreSQL.

Проблема: При работе с PostgreSQL использование соединения с виртуальной таблицей СрезПоследних может приводить к существенному снижению производительности. Из-за ошибки оптимизатора может быть выбран неоптимальный план выполнения запроса.

Решение: Если в запросе используется соединение с виртуальной таблицей языка запросов 1С:Предприятия СрезПоследних и запрос работает с неудовлетворительной производительностью, то рекомендуется вынести обращение к виртуальной таблице в отдельный запрос с сохранением результатов во временной таблице.

Решение проблемы с зависанием PostgreSQL.

При выполнения некоторых регламентных операций (Закрытие месяца, Расчет себестоимости и т.п.), где используются сложные запросы с большим количеством соединений больших таблиц, возможно существенное увеличение времени выполнения операции. В основном, эти проблемы связаны с работой оптимизатора PostgreSQL и отсутствием актуальной статистики по таблицам, участвующим в запросе.

Варианты решения проблемы:

  • Увеличить количество записей, просматриваемых при сборе статистики по таблицам. Большие значения могут повысить время выполнения команды ANALYZE , но улучшат построение плана запроса:
    • Файл postgresql.conf - default_statistics_target = 1000 -10000 .
  • Отключение оптимизатору возможности использования NESTED LOOP при выборе плана выполнения запроса в конфигурации PostgreSQL:
    • Файл postgresql.conf - enable_nestloop = off .
    • Отрицательным эффектом этого способа является возможное замедление некоторых запросов, поскольку при их выполении будут использоваться другие, более затратные, методы соединения (HASH JOIN).
  • Отключение оптимизатору возможности изменения порядка соединений таблиц в запросе:
    • Файл postgresql.conf - join_collapse_limit=1 .
    • Следует использовать этот метод, если вы уверены в правильности порядка соединений таблиц в проблемном запросе.
  • Изменение параметров настройки оптимизатора:
    • Файл postgresql.conf:
      • seq_page_cost = 0.1
      • random_page_cost = 0.4
      • cpu_operator_cost = 0.00025
  • Использование версии PostgreSQL 9.1.2-1.1.C и выше, в которой реализован независимый от AUTOVACUUM сбор статистики, на основе информации об изменении данных в таблице. По умолчанию включен сбор статистики только для временных таблиц и во многих ситуациях этого достаточно. При возникновении проблем с производительностью выполнения регламентных операций, можно включить сбор статистики для всех или отдельных проблемных таблиц изменив значение параметра конфигурации PostgreSQL (файл postgresql.conf ) online_analyze.table_type = "temporary" на online_analyze.table_type = "all" . мне товарищ Vasiliy P. Melnik. Несмотря на то, что интерфейс на английском, он простой и интуитивно понятный. Думаю каждый желающий сможет с ним разобраться.

Задаёт объём памяти, который будет использовать сервер баз данных для буферов в разделяемой памяти. По умолчанию это обычно 128 мегабайт (128MB), но может быть и меньше, если конфигурация вашего ядра накладывает дополнительные ограничения (это определяется в процессе initdb ). Это значение не должно быть меньше 128 килобайт. (Этот минимум зависит от величины BLCKSZ .) Однако для хорошей производительности обычно требуются гораздо большие значения. Задать этот параметр можно только при запуске сервера.

Если вы используете выделенный сервер с объёмом ОЗУ 1 ГБ и более, разумным начальным значением shared_buffers будет 25% от объёма памяти. Существуют варианты нагрузки, при которых эффективны будут и ещё большие значения shared_buffers , но так как Postgres Pro использует и кеш операционной системы, выделять для shared_buffers более 40% ОЗУ вряд ли будет полезно. При увеличении shared_buffers обычно требуется соответственно увеличить max_wal_size , чтобы растянуть процесс записи большого объёма новых или изменённых данных на более продолжительное время.

В серверах с объёмом ОЗУ меньше 1ГБ следует использовать меньший процент ОЗУ, чтобы оставить достаточно памяти для операционной системы. Кроме того, большие значения shared_buffers не так эффективны в Windows. Возможно, вы получите лучшие результаты, если оставите это значение относительно небольшим и будете больше полагаться на кеш операционной системы. Оптимальные значения shared_buffers для Windows обычно лежат в интервале от 64 до 512 мегабайт. huge_pages (enum)

Включает/отключает использование огромных страниц памяти. Допустимые значения: try (попытаться, по умолчанию), on (вкл.) и off (выкл.).

В настоящее время это поддерживается только в Linux. В других системах значение try просто игнорируется.

Когда huge_pages имеет значение try , сервер попытается использовать огромные страницы, но может переключиться на обычные, если это не удастся. Со значением on , если использовать огромные страницы не получится, сервер не будет запущен. Со значением off огромные страницы использоваться не будут. temp_buffers (integer)

Задаёт максимальное число временных буферов для каждого сеанса, По умолчанию объём временных буферов составляет восемь мегабайт (1024 буфера). Этот параметр можно изменить в отдельном сеансе, но только до первого обращения к временным таблицам; после этого изменить его значение для текущего сеанса не удастся.

Сеанс выделяет временные буферы по мере необходимости до достижения предела, заданного параметром temp_buffers . Если сеанс не задействует временные буферы, то для него хранятся только дескрипторы буферов, которые занимают около 64 байтов (в количестве temp_buffers). Однако если буфер действительно используется, он будет дополнительно занимать 8192 байта (или в общем случае, BLCKSZ байтов). max_prepared_transactions (integer)

Задаёт максимальное число транзакций, которые могут одновременно находиться в «подготовленном » состоянии (см. PREPARE TRANSACTION ). При нулевом значении (по умолчанию) механизм подготовленных транзакций отключается. Задать этот параметр можно только при запуске сервера.

Если использовать транзакции не планируется, этот параметр следует обнулить, чтобы не допустить непреднамеренного создания подготовленных транзакций. Если же подготовленные транзакции применяются, то max_prepared_transactions , вероятно, должен быть не меньше, чем max_connections , чтобы подготовить транзакцию можно было в каждом сеансе.

Для ведомого сервера значение этого параметра должно быть больше или равно значению на ведущем. В противном случае на ведомом сервере не будут разрешены запросы. work_mem (integer)

Задаёт объём памяти, который будет использоваться для внутренних операций сортировки и хеш-таблиц, прежде чем будут задействованы временные файлы на диске. Значение по умолчанию - четыре мегабайта (4MB). Заметьте, что в сложных запросах одновременно могут выполняться несколько операций сортировки или хеширования, так что этот объём памяти будет доступен для каждой операции. Кроме того, такие операции могут выполняться одновременно в разных сеансах. Таким образом, общий объём памяти может многократно превосходить значение work_mem ; это следует учитывать, выбирая подходящее значение. Операции сортировки используются для ORDER BY , DISTINCT и соединений слиянием. Хеш-таблицы используются при соединениях и агрегировании по хешу, а также обработке подзапросов IN с применением хеша. maintenance_work_mem (integer)

Задаёт максимальный объём памяти для операций обслуживания БД, в частности VACUUM , CREATE INDEX и ALTER TABLE ADD FOREIGN KEY . По умолчанию его значение - 64 мегабайта (64MB). Так как в один момент времени в сеансе может выполняться только одна такая операция, и обычно они не запускаются параллельно, это значение вполне может быть гораздо больше work_mem . Увеличение этого значения может привести к ускорению операций очистки и восстановления БД из копии.

Учтите, что когда выполняется автоочистка, этот объём может быть выделен autovacuum_max_workers раз, поэтому не стоит устанавливать значение по умолчанию слишком большим. Возможно, будет лучше управлять объёмом памяти для автоочистки отдельно, изменяя . replacement_sort_tuples (integer)

Когда количество сортируемых кортежей меньше заданного числа, для получения первого потока сортируемых данных будет применяться не алгоритм quicksort, а выбор с замещением. Это может быть полезно в системах с ограниченным объёмом памяти, когда кортежи, поступающие на вход большой операции сортировки, характеризуются хорошей корреляцией физического и логического порядка. Заметьте, что это не относится к кортежам с обратной корреляцией. Вполне возможно, что алгоритм выбора с замещением сформирует один длинный поток и слияние не потребуется, тогда как со стратегией по умолчанию может быть получено много потоков, которые затем потребуется слить для получения окончательного отсортированного результата. Это позволяет ускорить операции сортировки.

Значение по умолчанию - 150000 кортежей. Заметьте, что увеличивать это значение обычно не очень полезно, и может быть даже контрпродуктивно, так как эффективность приоритетной очереди зависит от доступного объёма кеша процессора, тогда как со стандартной стратегией потоки сортируются кеш-независимым алгоритмом. Благодаря этому, стандартная стратегия позволяет автоматически и прозрачно использовать доступный кеш процессора более эффективным образом.

Если в maintenance_work_mem задано значение по умолчанию, внешние сортировки в служебных командах (например, сортировки, выполняемые командами CREATE INDEX для построения-индекса B-дерева) обычно никогда не используют алгоритм выбора с замещением (так как все кортежи помещаются в память), кроме случаев, когда входные кортежи достаточно велики. autovacuum_work_mem (integer)

Задаёт максимальный объём памяти, который будет использовать каждый рабочий процесс автоочистки. По умолчанию равен -1, что означает, что этот объём определяется значением . Этот параметр не влияет на поведение команды VACUUM , выполняемой в других контекстах. max_stack_depth (integer)

Задаёт максимальную безопасную глубину стека для исполнителя. В идеале это значение должно равняться предельному размеру стека, ограниченному ядром (как устанавливает команда ulimit -s или равнозначные ей), за вычетом запаса примерно в мегабайт. Этот запас необходим, потому что сервер проверяет глубину стека не в каждой процедуре, а только в потенциально рекурсивных процедурах, например, при вычислении выражений. Значение по умолчанию - два мегабайта (2MB), выбрано с большим запасом, так что риск переполнения стека минимален. Однако, с другой стороны, его может быть недостаточно для выполнения сложных функций. Изменить этот параметр могут только суперпользователи.

Если max_stack_depth будет превышать фактический предел ядра, то функция с неограниченной рекурсией сможет вызвать крах отдельного процесса сервера. В системах, где Postgres Pro может определить предел, установленный ядром, он не позволит установить для этого параметра небезопасное значение. Однако эту информацию выдают не все системы, поэтому выбирать это значение следует с осторожностью. dynamic_shared_memory_type (enum)

Выбирает механизм динамической разделяемой памяти, который будет использовать сервер. Допустимые варианты: posix (для выделения разделяемой памяти POSIX функцией shm_open), sysv (для выделения разделяемой памяти System V функцией shmget), windows (для выделения разделяемой памяти в Windows), mmap (для эмуляции разделяемой памяти через отображение в память файлов, хранящихся в каталоге данных) и none (для отключения этой функциональности). Не все варианты поддерживаются на разных платформах; первый из поддерживаемых данной платформой вариантов становится для неё вариантом по умолчанию. Применять mmap , который нигде не выбирается по умолчанию, вообще не рекомендуется, так как операционная система может периодически записывать на диск изменённые страницы, что создаст дополнительную нагрузку; однако, это может быть полезно для отладки, когда каталог pg_dynshmem находится в RAM-диске или когда другие механизмы разделяемой памяти недоступны.

18.4.2. Диск

Примерная стоимость очистки буфера, оказавшегося в общем кеше. Это подразумевает блокировку пула буферов, поиск в хеш-таблице и сканирование содержимого страницы. По умолчанию этот параметр равен одному. vacuum_cost_page_miss (integer)

Примерная стоимость очистки буфера, который нужно прочитать с диска. Это подразумевает блокировку пула буферов, поиск в хеш-таблице, чтение требуемого блока с диска и сканирование его содержимого. По умолчанию этот параметр равен 10. vacuum_cost_page_dirty (integer)

Примерная стоимость очистки, при которой изменяется блок, не модифицированный ранее. В неё включается дополнительная стоимость ввода/вывода, связанная с записью изменённого блока на диск. По умолчанию этот параметр равен 20. vacuum_cost_limit (integer)

Общая стоимость, при накоплении которой процесс очистки будет засыпать. По умолчанию этот параметр равен 200.

Примечание

Некоторые операции устанавливают критические блокировки и поэтому должны завершаться как можно быстрее. Во время таких операций задержка очистки по стоимости не осуществляется, так что накопленная за это время стоимость может намного превышать установленный предел. Во избежание ненужных длительных задержек в таких случаях, фактическая задержка вычисляется по формуле vacuum_cost_delay * accumulated_balance / vacuum_cost_limit и ограничивается максимумом, равным vacuum_cost_delay * 4.

18.4.5. Фоновая запись

В числе специальных процессов сервера есть процесс фоновой записи , задача которого - осуществлять запись «грязных » (новых или изменённых) общих буферов на диск. Он старается записывать данные из буферов так, чтобы обычным серверным процессам, обрабатывающим запросы, не приходилось ждать записи или это ожидание было минимальным. Однако процесс фоновой записи увеличивает общую нагрузку на подсистему ввода/вывода, так как он может записывать неоднократно изменяемую страницу при каждом изменении, тогда как она может быть записана всего раз в контрольной точке. Параметры, рассматриваемые в данном подразделе, позволяют настроить поведение фоновой записи для конкретных нужд.

Задаёт максимальное число буферов, которое сможет записать процесс фоновой записи за раунд активности. При нулевом значении фоновая запись отключается. (Учтите, что на контрольные точки, которые управляются отдельным вспомогательным процессом, это не влияет.) По умолчанию значение этого параметра - 100 буферов. Задать этот параметр можно только в postgresql.conf или в командной строке при запуске сервера. bgwriter_lru_multiplier (floating point)

Число загрязнённых буферов, записываемых в очередном раунде, зависит от того, сколько новых буферов требовалось серверным процессам в предыдущих раундах. Средняя недавняя потребность умножается на bgwriter_lru_multiplier и предполагается, что именно столько буферов потребуется на следующем раунде. Процесс фоновой записи будет записывать на диск и освобождать буферы, пока число свободных буферов не достигнет целевого значения. (При этом число буферов, записываемых за раунд, ограничивается сверху параметром bgwriter_lru_maxpages .) Таким образом, со множителем, равным 1.0, записывается ровно столько буферов, сколько требуется по предположению («точно по плану » ). Увеличение этого множителя даёт некоторую страховку от резких скачков потребностей, тогда как уменьшение отражает намерение оставить некоторый объём записи для серверных процессов. По умолчанию он равен 2.0. Этот параметр можно установить только в файле postgresql.conf или в командной строке при запуске сервера. bgwriter_flush_after (integer)

Когда процессом фоновой записи записывается больше чем bgwriter_flush_after байт, сервер даёт указание ОС произвести запись этих данных в нижележащее хранилище. Это ограничивает объём «грязных» данных в страничном кеше ядра и уменьшает вероятность затормаживания при выполнении fsync в конце контрольной точки или когда ОС сбрасывает данные на диск большими порциями в фоне. Часто это значительно уменьшает задержки транзакций, но бывают ситуации, особенно когда объём рабочей нагрузки больше , но меньше страничного кеша ОС, когда производительность может упасть. Этот параметр действует не на всех платформах. Он может принимать значение от 0 (при этом управление отложенной записью отключается) до 2 Мбайт (2MB). Значение по умолчанию - 512kB в Linux и 0 в других ОС. (Если BLCKSZ отличен от 8 Кбайт, значение по умолчанию и максимум корректируются пропорционально.) Задать этот параметр можно только в postgresql.conf или в командной строке при запуске сервера.

С маленькими значениями bgwriter_lru_maxpages и bgwriter_lru_multiplier уменьшается активность ввода/вывода со стороны процесса фоновой записи, но увеличивается вероятность того, что запись придётся производить непосредственно серверным процессам, что замедлит выполнение запросов.

18.4.6. Асинхронное поведение

Effective_io_concurrency (integer)

Задаёт допустимое число параллельных операций ввода/вывода, которое говорит Postgres Pro о том, сколько операций ввода/вывода могут быть выполнены одновременно. Чем больше это число, тем больше операций ввода/вывода будет пытаться выполнить параллельно Postgres Pro в отдельном сеансе. Допустимые значения лежат в интервале от 1 до 1000, а нулевое значение отключает асинхронные запросы ввода/вывода. В настоящее время этот параметр влияет только на сканирование по битовой карте.

Для магнитных носителей хорошим начальным значением этого параметра будет число отдельных дисков, составляющих массив RAID 0 или RAID 1, в котором размещена база данных. (Для RAID 5 следует исключить один диск (как диск с чётностью).) Однако, если база данных часто обрабатывает множество запросов в различных сеансах, и при небольших значениях дисковый массив может быть полностью загружен. Если продолжать увеличивать это значение при полной загрузке дисков, это приведёт только к увеличению нагрузки на процессор. Диски SSD и другие виды хранилища в памяти часто могут обрабатывать множество параллельных запросов, так что оптимальным числом может быть несколько сотен.

Асинхронный ввод/вывод зависит от эффективности функции posix_fadvise , которая отсутствует в некоторых операционных системах. В случае её отсутствия попытка задать для этого параметра любое ненулевое значение приведёт к ошибке. В некоторых системах (например, в Solaris), эта функция присутствует, но на самом деле ничего не делает.

Значение по умолчанию равно 1 в системах, где это поддерживается, и 0 в остальных. Это значение можно переопределить для таблиц в определённом табличном пространстве, установив одноимённый параметр табличного пространства (см. ALTER TABLESPACE ). max_worker_processes (integer)

Задаёт максимальное число фоновых процессов, которое можно запустить в текущей системе. Этот параметр можно задать только при запуске сервера. Значение по умолчанию - 8.

Для ведомого сервера значение этого параметра должно быть больше или равно значению на ведущем. В противном случае на ведомом сервере не будут разрешены запросы. max_parallel_workers_per_gather (integer)

Задаёт максимальное число рабочих процессов, которые могут запускаться одним узлом Gather . Параллельные рабочие процессы берутся из пула процессов, контролируемого параметром . Учтите, что запрошенное количество рабочих процессов может быть недоступно во время выполнения. В этом случае план будет выполняться с меньшим числом процессов, что может быть неэффективно. Значение 0 (заданное по умолчанию) отключает параллельное выполнение запросов.

Учтите, что параллельные запросы могут потреблять значительно больше ресурсов, чем не параллельные, так как каждый рабочий процесс является отдельным процессом и оказывает на систему примерно такое же влияние, как дополнительный пользовательский сеанс. Это следует учитывать, выбирая значение этого параметра, а также настраивая другие параметры, управляющие использованием ресурсов, например . Ограничения ресурсов, такие как work_mem , применяются к каждому рабочему процессу отдельно, что означает, что общая нагрузка для всех процессов может оказаться гораздо больше, чем при обычном использовании одного процесса. Например, параллельный запрос, задействующий 4 рабочих процесса, может использовать в 5 раз больше времени процессора, объёма памяти, ввода/вывода и т. д., по сравнению с запросом, не задействующим рабочие процессы вовсе.

За дополнительными сведениями о параллельных запросах обратитесь к Главе 15 . backend_flush_after (integer)

Когда одним обслуживающим процессом записывается больше backend_flush_after байт, сервер даёт указание ОС произвести запись этих данных в нижележащее хранилище. Это ограничивает объём «грязных» данных в страничном кеше ядра и уменьшает вероятность затормаживания при выполнении fsync в конце контрольной точки или когда ОС сбрасывает данные на диск большими порциями в фоне. Часто это значительно сокращает задержки транзакций, но бывают ситуации, особенно когда объём рабочей нагрузки больше , но меньше страничного кеша ОС, когда производительность может упасть. Этот параметр действует не на всех платформах. Он может принимать значение от 0 (при этом управление отложенной записью отключается) до 2 Мбайт (2MB). По умолчанию он имеет значение 0 , то есть это поведение отключено. (Если BLCKSZ отличен от 8 Кбайт, максимальное значение корректируется пропорционально.) old_snapshot_threshold (integer)

Задаёт минимальное время, которое можно пользоваться снимком без риска получить ошибку снимок слишком стар. Этот параметр можно задать только при запуске сервера.

По истечении этого времени старые данные могут вычищены. Это предотвращает замусоривание данными снимков, которые остаются задействованными долгое время. Во избежание получения некорректных результатов из-за очистки данных, которые должны были бы наблюдаться в снимке, клиенту будет выдана ошибка, если возраст снимка превысит заданный предел и из этого снимка будет запрошена страница, изменённая со времени его создания.

Значение -1 (по умолчанию) отключает это поведение. Полезные значения для производственной среды могут лежать в интервале от нескольких часов до нескольких дней. Заданное значение округляется до минут, а минимальные значения (как например, 0 или 1min) допускаются только потому, что они могут быть полезны при тестировании. Хотя допустимым будет и значение 60d (60 дней), учтите, что при многих видах нагрузки критичное замусоривание базы или зацикливание идентификаторов транзакций может происходить в намного меньших временных отрезках.

Когда это ограничение действует, освобождённое пространство в конце отношения не может быть отдано операционной системе, так как при этом будет удалена информация, необходимая для выявления условия снимок слишком стар. Всё пространство, выделенное отношению, останется связанным с ним до тех пор, пока не будет освобождено явно (например, с помощью команды VACUUM FULL).

Установка этого параметра не гарантирует, что обозначенная ошибка будет выдаваться при всех возможных обстоятельствах. На самом деле, если можно получить корректные результаты, например, из курсора, материализовавшего результирующий набор, ошибка не будет выдана, даже если нижележащие строки в целевой таблице были ликвидированы при очистке. Некоторые таблицы не могут быть безопасно очищены в сжатые сроки, так что на них этот параметр не распространяется. В частности, это касается системных каталогов и таблиц с хеш-индексами. Для таких таблиц этот параметр не сокращает раздувание, но и не чреват ошибкой снимок слишком стар при сканировании.