Postgresql кэш на отдельный диск. БД — большой кэш. Прочие параметры, влияющие на производительность

Данная статья не претендует на полноту изложения всех возможностей конфигурирования PostgreSQL, и в сравнительном тестировании я не охватываю всех режимов работы базы данных. Заинтересовавшимся советую изучить книгу по ссылке

Вступление

Я много работал с PostgreSQL и считаю его прекрасной СУБД. У меня многогигабайтная рабочая база (не 1С) обрабатывает моментально огромные массивы данных. PostgreSQL прекрасно использует индексы, хорошо справляется с параллельной нагрузкой, функционал хранимых процедур на высоте, есть хорошие средства администрирования и повышения производительности "из коробки", а сообщество создало полезные утилиты. Но я с удивлением узнал что у многих администраторов 1С мнение о PostgreSQL не на высоте, что он тормоз и едва обгоняет файловый вариант базы, и только MSSQL может спасти положение.

Поизучав вопрос, я нашел множество статей по установке PostgreSQL по шагам для чайников, как по Linux, так и под Windows. Но подавляющее большинство статей описывают установку до "установилось - создадим базу", и совершенно не затрагивают вопрос конфигурирования. В оставшихся конфигурирование упоминается лишь на уровне "прописать такие значения", практически не объясняя зачем.

И если подход "установка в одну кнопку" применим к MSSQL и вообще многим продуктам под Windows, то к PostgreSQL он, к сожалению, не относится. Настройки по умолчанию очень сильно ограничивают его в использовании памяти, чтобы можно было его установить хоть на калькулятор и он там не мешал работе остального ПО. PostgreSQL обязательно нужно конфигурировать под конкретную систему, и только тогда он сможет показать себя на высоте. В особо тяжелых случаях можно тюнинговать настройки PostgreSQL, базы и файловой системы друг под друга, но это касается в большей степени Linux-систем, где больше возможностей по настройке всего и вся.

Следует напомнить, что для 1С не подойдет сборка PostgreSQL от разработчиков СУБД, только собранная из пропатченных 1С исходных текстов. Готовые совместимые сборки предлагает 1С (через диски ИТС и кабинет для имеющих подписку на поддержку) и EterSoft

Тестирование проводилось в среде Windows, но все рекомендации по настройке не являются специфичными для платформы и применимы к любой ОС.

Тестирование и сравнение

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

Для тестирования я использовал следующую конфигурацию:
Host-машина: Win7, Core i5-760 2.8MHz, 4 ядра, 12Гб ОЗУ, VMWare 10
Виртуальная: Win7 x64, 2 ядра, 4Гб ОЗУ, отдельный физический жесткий диск для размещения БД (не SSD)
MSSQL Express 2014
PostgreSQL EtherSoft 9.2.1
1C 8.3.5 1383

Использовалась БД, dt-выгрузка 780Мб.
После восстановления базы:
размер файла 1CD в файловом варианте - 10Гб,
размер базы PostgreSQL - 8Гб,
размер базы MSSQL - 6.7Гб.

Для теста использовал запрос на выборку договоров контрагентов (21к) с выборкой дополнительных реквизитов из различных регистров, для каждого договора фактически делалась отдельная выборка из регистров. Конфигурацию взял что была под рукой - сильно доработанная на базе Бухгалтерии 3.0.

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

Тестирование одним клиентом:

Выборка на хосте из файлового варианта с размещением базы на SSD - 31с
Выборка из файлового варианта в виртуальной машине (с жесткого диска) - 46с
Выборка из MSSQL-базы - первый проход - 25с или 9с (видимо в зависимости от актуальности кэша СУБД) (потребление памяти процессом СУБД составило примерно 1.3Гб)
Выборка из PostgreSQL с настройками по умолчанию - 43с (потребление памяти не превышало 80Мб на подключение)
Выборка из оптимизированного PostgreSQL - 21с (потребление памяти составило 120Мб на подключение)

Тестирование двумя клиентами:

Выборка на хосте из файлового варианта с размещением базы на SSD - по 34с
Выборка из файлового варианта в виртуальной машине (с жесткого диска) - по 56с
Выборка из MSSQL-базы - по 50с или 20с (видимо в зависимости от актуальности кэша СУБД)
Выборка из PostgreSQL с настройками по умолчанию - по 60с
Выборка из оптимизированного PostgreSQL - по 40с

Замечания к тестированию:

  1. После добавления третьего ядра PostgreSQL и MSSQL-варианты стали работать в тесте "два клиента" практически с производительностью теста "один клиент", т.е. удачно распараллелились. Что мешало им параллелить работу на двух ядрах для меня осталось загадкой.
  2. MSSQL памяти захватил сразу много, PostgreSQL требовал во всех режимах существенно меньше, и сразу после завершения выполнения запроса почти всю высвобождал.
  3. MSSQL работает единым процессом. PostgreSQL запускает по отдельному процессу на подключение+служебные процессы. Это позволяет даже 32-разрядному варианту эффективно использовать память при обработке запросов от нескольких клиентов.
  4. Увеличение памяти для PostgreSQL в настройках свыше указанных ниже значений не привело к заметному росту производительности.
  5. Первые тесты во всех случаях проходили дольше чем в последующих замерах, специально замеры не производил, но MSSQL субъективно стартовал быстрее.

Конфигурирование PostgreSQL

Есть прекрасная книга на русском языке о конфигурировании и оптимизировании PostgreSQL: Каждому слоноводу имеет смысл поставить себе в закладки эту ссылку. В книге описывается множество техниг оптимизации СУБД, создание отказоустойчивых и распределенных систем. Но сейчас мы рассмотрим то что пригодится всем - конфигурирование использования памяти. PostgreSQL не будет использовать памяти больше чем разрешено настройками, а с настройками по умолчанию PostgreSQL использует минимум памяти. При этом не стоит указывать памяти больше чем доступно к использованию - система начнет использовать файл подкачки со всеми вытекающими печальными последствиями для производительности сервера. Ряд советов по настройке PostgreSQL приведены на диске ИТС.

В Windows конфигурационные файлы PostgreSQL находятся в каталоге установки в каталоге Data:

  • postgresql.conf - основной файл с настройками СУБД
  • pg_hba.conf - файл с настройками доступа для клиентов. В частности, тут можно указать каким пользователям с каких IP-адресов можно подключаться к определенным БД, и требуется ли проверять пароль пользователя, и если требуется - каким методом.
  • pg_ident.conf - файл с преобразованием имен пользователей из системных во внутренние (вряд ли он потребуется большинству пользователей)

Файлы текстовые, можно править блокнотом. Строки, начинающиеся с # считаются комментариями и игнорируются.

Параметры, относящиеся к объму памяти могут дополняться суффиксами kB, MB, GB - килобайты, мегабайты, гигабайты, например, 128MB. Параметры, описывающие интервалы времени, могут дополняться суффиксами ms,s,min,h,d - миллисекунды, секунды, минуты, часы, дни, например, 5min

Если вы забыли пароль к постгрессу - не беда, можно прописать в pg_hba.conf строку:

Host all all 127.0.0.1/32 trust

И подключаться любым пользователем (например, postgres ) к СУБД на локальной машине по адресу 127.0.0.1 без проверки пароля.

Оптимизация использования памяти

Настройки использования памяти располагаются в postgresql.conf

Оптимальные значения параметров зависят от объема свободной оперативной памяти, размера базы и отдельных элементов базы (таблицы и индексы), сложности запросов (в принципе, стоит полагаться что запросы будут достаточно сложными - множественные соединения в запросах это типовой сценарий) и количества одновременных активных клиентов. Кстати, PostgreSQL хранит таблицы и индексы БД в отдельных файлах (<каталог установки PG>\data\base\<идентификатор БД>\), и размеры объектов можно оценить. Так же можно используя входящую в поставку утилиту pgAdmin подключиться к базе, раскрыть "Схемы"-"public", и сформировать отчет по статистике для элемента "Таблицы".

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

При настройке сервера для тестирования я полагался на следующие расчеты:
Всего 4Гб ОЗУ. Потребители - ОС Windows, сервер 1С, PostgreSQL и дисковый кэш системы. Я исходил из того что для СУБД можно выделить до 2.5Гб ОЗУ

Значения могут указываться с суффиксами kB, MB, GB (значения в килобайта, мегабайтах или гигабайтах). После изменения значений требуется перезапустить службу PostgreSQL.

shared_buffers - Общий буфер сервера

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

Если объём буфера недостаточен для хранения часто используемых рабочих данных, то они будут постоянно писаться и читаться из кэша ОС или с диска, что крайне отрицательно скажется на производительности.

Но это не вся память, требуемая для работы, не следует указывать слишком большое значение, иначе не останется памяти как для собственно выполнения запросов клиентов (а чем их больше тем выше потребление памяти), так и для ОС и прочих приложений, например, процесса сервера 1С. Так же сервер полагается и на кэш ОС и старается не держать в своём буфере то что скорее всего закэшировано системой.

В тесте использовалось

shared_buffers = 512MB

work_mem - память для сортировки, агрегации данных и т.д.

Выделяется на каждый запрос, возможно по нескольку раз для сложных запросов. Если памяти недостаточно - PostgreSQL будет использовать временные файлы. Если значение слишком большое - может возникнуть перерасход оперативной памяти и ОС начнет использовать файл подкачки с соответствующим падением быстродействия.

Есть рекомендация при расчетах взять объем доступной памяти за вычетом shared_buffers , и поделить на количество одновременно исполняемых запросов. В случае сложных запросов делитель стоит увеличить, т.е. уменьшить результат. Для рассматриваемого случая из расчета 5 активных пользователей (2.5Гб-0.5Гб (shared_buffers))/5=400Мб. В случае если СУБД сочтет запросы достаточно сложными, или появятся дополнительные пользователи, потребуется значение уменьшить.

Для простых запросов достаточно небольших значений - до пары мегабайт, но для сложных запросов (а это типовой сценарий для 1С) потребуется больше. Рекомендация - для памяти 1-4Гб можно использовать значения 32-128Мб. В тесте использовал

work_mem = 128MB

maintenance_work_mem - память для команд сбора мусора, статистики, создания индексов.

Рекомендуется устанавливать значение 50-75% от размера самой большой таблицы или индекса, но чтобы памяти хватило для работы системы и приложений. Рекомендуется устанавливать значения больше чем work_mem. В тесте использовал
maintenance_work_mem = 192MB

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

Можно установить порядка 16 МБ. В тесте использовал
temp_buffers = 32MB

effective_cache_size - примерный объем дискового кэша файловой системы.

Оптимизатор использует это значение при построении плана запроса, для оценки вероятности нахождения данных в кэше (с быстрым случайным доступом) или на медленном диске. В Windows текущий объем памяти, выделенной под кэш, можно посмотреть в диспетчере задач.

Autovacuum - "сборка мусора"

PostgreSQL как типичный представитель "версионных" СУБД (в противоположность блокирующим) самостоятельно не блокирует при изменении данных таблицы и записи от читающих транзакций (в случае 1С этим занимается сам сервер 1С). Вместо этого создаётся копия изменяемой записи, которая становится видна последующим транзакциям, действующие же продолжают видеть данные, актуальные на начало своей транзакции. Как следствие, в таблицах накапливаются устаревшие данные - предыдущие версии измененных записей. Для того чтобы СУБД могла высвободившееся место использовать, необходимо произвести "сборку мусора" - определить какие из записей больше не используются. Это можно сделать явно SQL-командой VACUUM , либо дождаться когда таблицу обработает автоматический сборщик мусора - AUTOVACUUM . Так же до определенной версии сборка мусора была связана со сбором статистики (планировщик использует данные о количестве записей в таблицах и распределении значений индексированных полей для построения оптимального плана запроса). С одной стороны, сбор мусора делать необходимо, чтобы таблицы не разрастались и эффективно использовали дисковое пространство. С другой внезапно начавшаяся уборка мусора дает дополнительную нагрузку на диск и таблицы, что приводит к увеличению времени выполнения запросов. Аналогичный эффект создает автоматический сбор статистики (явно его можно запустить командой ANALYZE или совместно со сборкой мусора VACUUM ANALYZE ). И хотя от версии к версии PostgreSQL совершенствует эти механизмы, чтобы минимизировать негативное влияние на производительность (например, в ранних версиях сборка мусора полностью блокировала доступ к таблице, с версии 9.0 работа VACUUM ускорена), тут есть что настроить.

Полностью отключить autovacuum можно параметром:

autovacuum = off

Так же для работы Autovacuum требуется параметр track_counts = on, в противном случае он работать не будет.

По умолчанию оба параметра включены. На самом деле autovacuum полностью отключить нельзя - даже при autovacuum = off иногда (после большого количества транзакций) autovacuum будет запускаться.

Замечание: VACUUM обычно не уменьшает размер файла таблицы, только помечает свободные, доступные для повторного использования области. Если же требуется физически высвободить лишнее место и максимально уменьшить занимаемое пространство на диске, потребуется команда VACUUM FULL . Этот вариант блокирует доступ к таблице на время работы, и обычно не требуется его использовать. Подробнее об использовании команды VACUUM можно прочитать в документации (на английском).

Если Autovacuum полностью не отключать, настроить его влияние на выполнение запросов можно следующими параметрами:

autovacuum_max_workers - максимальное количество параллельно запущенных процессов уборки.

autovacuum_naptime - минимальный интервал, реже которого autovacuum не будет запускаться. По умолчанию 1 минута. Можно увеличить, тогда при частых изменениях данных анализ будет выполняться реже.

autovacuum_vacuum_threshold, - количество измененных или удаленных записей в таблице, необходимых для запуска процесса сборки мусора VACUUM или сбора статистики ANALYZE . По умолчанию по 50.

autovacuum_vacuum_scale_factor , autovacuum_analyze_scale_factor - коэфициент от размера таблицы в записях, добавляемый к autovacuum_vacuum_threshold и autovacuum_analyze_threshold соответственно. Значения по умолчанию 0.2 (т.е. 20% от количества записей) и 0.1 (10%) соответственно.

Рассмотрим пример с таблицей на 10000 записей. Тогда при настройках по умолчанию после 50+10000*0.1=1050 измененных или удаленных записей будет запущен сбор статистики ANALYZE , а после 2050 изменений - сборка мусора VACUUM .

Если увеличить threshold и scale_factor, обслуживающие процессы будут выполняться реже, но небольшие таблицы могут существенно разрастаться. Если БД состоит преимущественно из небольших таблиц, общее увеличение занимаемого дискового пространства может быть существенным, таким образом увеличивать эти значения можно, но с умом.

Таким образом может иметь смысл увеличить интервал autovacuum_naptime, и несколько увеличить threshold и scale_factor. В нагруженных базах может быть альтернативой существенно поднять scale_factor (значение 1 позволит "разбухать" таблицам вдвое) и поставить в планировщик ежесуточное выполнение VACUUM ANALYZE в период минимальной загруженности БД.

default_statistics_target - назначает объем статистики, собираемый командой ANALYZE . Значение по умолчанию 100. Большие значения увеличивают время выполнения команды ANALYZE, но позволяют планировщику строить более эффективные планы выполнения запросов. Встречаются рекомендации по увеличению до 300.

Можно управлять производительностью AUTOVACUUM , делая его более длительным но менее нагружающим систему.

vacuum_cost_page_hit - размер "штрафа" за обработку блока, находящегося в shared_buffers. Связан с необходимостью блокировать доступ к буферу. Значение по умолчанию 1

vacuum_cost_page_miss - размер "штрафа" за обработку блока на диске. Связан с блокировкой буфера, поиском данных в буфере, чтении данных с диска. Значение по умолчанию 10

vacuum_cost_page_dirty - размер "штрафа" за модификацию блока. Связан с необходимостью сбросить модифицированные данные на диск. Значение по умолчанию 20

vacuum_cost_limit - максимальный размер "штрафов", после которых процесс сборки может быть "заморожен" на время vacuum_cost_delay. По умолчанию 200

vacuum_cost_delay - время "заморозки" процесса сборки мусора по достижению vacuum_cost_limit. Значение по умолчанию 0ms

autovacuum_vacuum_cost_delay - время "заморозки" процесса сборки мусора для autovacuum. По умолчанию 20ms. Если установить -1, будет использоваться значение vacuum_cost_delay

autovacuum_vacuum_cost_limit - максимальный размер "штрафа" для autovacuum. Значение по умолчанию -1 - используется значение vacuum_cost_limit

По сообщениям использование vacuum_cost_page_hit = 6 , vacuum_cost_limit = 100 , autovacuum_vacuum_cost_delay = 200ms уменьшает влияние AUTOVACUUM до 80%, но увеличивает время его выполнения втрое.

Настройка записи на диск

При завершении транзакции PostgreSQL начала пишет данные в специальный журнал транзакций WAL (Write-ahead log), а затем уже в базу после того, как данные журнала гарантированно записаны на диск. По умолчанию используется механизм fsync , когда PostgreSQL принудительно сбрасывает данные (журнала) из дискового кэша ОС на диск, и только после успешной записи (журнала) клиенту сообщается об успешном завершении транзакции. Использование журнала транзакций позволяет завершить транзакцию или восстановить базу если во время записи данных произойдет сбой.

В нагруженных системах с большими объемами записи может иметь смысл вынести журнал транзакций на отдельный физический диск (но не на другой раздел этого же диска!). Для этого нужно остановить СУБД, перенести каталог pg_xlog в другое место, а на старом месте создать символическую ссылку, например, утилитой junction. Так же ссылки умеет создавать Far Manager (Alt-F6). При этом надо убедиться что новое место имеет права доступа для пользователя, от которого запускается PostgreSQL (обычно postgres).

При большом количестве операций изменения данных может потребоваться увеличить значение checkpoint_segments, регулирующее объем данных, который может ожидать переноса из журнала в саму базу. По умолчанию используется значение 3. При этом следует учитывать что под журнал выделяется место, расчитываемое по формуле (checkpoint_segments * 2 + 1) * 16 МБ, что при значении 32 уже потребует более 1Гб места на диске.

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

fsync = off
full_page_writes = off

Делать это можно только в случае если вы на 100% доверяете оборудованию и ИБП (источнику бесперебойного питания). Иначе в случае аварийного завершения системы есть риск получить разрушенную БД. И в любом варианте не помешает так же RAID-контроллер с батарейкой для питания памяти недозаписанных данных.

Определенной альтернативой может быть использование параметра

synchronous_commit = off

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

Если не отключать fsync совсем, можно указать метод синхронизации в параметре. Статья с диска ИТС ссылается на утилиту pg_test_fsync, но в моей сборке PostgreSQL её не оказалось. По утверждению 1С, в их случае в Windows оптимально себя показал метод open_datasync (судя по всему, именно этот метод и используется по умолчанию).

В случае если используется множество мелких пишущих транзакций (в случае 1С этом может быть массовое обновление справочника вне транзакции), может помочь сочетание параметров commit_delay (время задержки завершения транзакции в микросекундах, по умолчанию 0) и commit_siblings (по умолчанию 5). При включении опций завершение транзакции может быть отложено на время commit_delay, если в данный момент исполняется не менее commit_siblings транзакций. В этом случае результат всех завершившихся транзакций будет записан совместно для оптимизации записи на диск.

Прочие параметры, влияющие на производительность

wal_buffers - объем памяти в shared_buffers для ведения транзакционных логов. Рекомендация - при 1-4Гб доступной памяти использовать значения 256КБ-1МБ. Документация утверждает что использование значения "-1" автоматически подбирает значение в зависимости от значения shared_buffers.

random_page_cost - "стоимость" случайного чтения, используется при поиске данных по индексам. По умолчанию 4.0. За единицу берется время последовательного доступа к данным. Для быстрых дисковых массивов, особенно SSD, имеет смысл понижать значение, в этом случае PostgreSQL будет более активно использовать индексы.

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

Параметры из раздела QUERY TUNING, особенно касающиеся запрета планировщику использовать конкретные методы поиска, рекомендуется изменять только в том случае если есть полное понимание что делаете. Очень легко оптимизировать один вид запросов и обрушить производительность всех остальных. Эффективность изменения большинства параметров в этом разделе зависит от данных в БД, запросов к этим данным (т.е. от используемой версии 1С в т.ч.) и версии СУБД.

Заключение

PostgreSQL - мощная СУБД в умелых руках, но требующая тщательной настройки. Его вполне можно использовать совместно с 1С и получить приличное быстродействие, а бесплатность его будет очень приятным бонусом.

Критика и дополнения к этой статье приветствуются.

Полезные ссылки

http://postgresql.leopard.in.ua/ - сайт книги "Работа с PostgreSQL настройка и масштабирование ", наиболее полное и понятное руководство на мой взгляд по конфигурированию и администрированию PostgreSQL

http://etersoft.ru/products/postgre - здесь можно скачать 1С-совместимую сборку PostgreSQL под Windows и различные дистрибутивы и версии Linux. Для тех у кого нет подписки на ИТС или требуется версия под версию Linux, которая не представлена на v8.1c.ru.

http://www.postgresql.org/docs/9.2/static/ - официальная документация на PostgreSQL (на английском)

Статьи с диска ИТС по настройке PostgreSQL

История правок статьи

  • 29.01.2015 - опубликована первоначальная версия
  • 31.01.2015 - статья дополнена разделом по AUTOVACUUM, добавлена ссылка на оригинальную документацию.

В дальнейшем я намерен провести тестирование работы СУБД в режиме добавления и изменения данные.

По умолчанию PostgreSQL настроен таким образом, чтобы расходовать минимальное количество ресурсов для работы с небольшими базами до 4 Gb на не очень производительных серверах. То есть, если дело касается систем посерьезней, то вы столкнетесь с большими потерями производительности базы данных лишь потому, что дефолтные настройки могут в корне не соответствовать производительности вашего северного оборудования. Настройки выделения ресурсов оперативной памяти RAM для работы PostgreSQL хранятся в файле postgresql.conf .

Доступен как из папки, куда установлен PostgreSQL / Data, так и из pgAdmin:

В общем на начальном этапе при возникновении трудностей и замедления работы БД, заметной для глаз пользователей достаточно увеличить три параметра:

shared_buffers

Это размер памяти, разделяемой между процессами PostgreSQL, отвечающими за выполнения активных операций. Максимально-допустимое значение этого параметра – 25% всего количества RAM

Например, при 1-2 Gb RAM на сервере, достаточно указать в этом параметре значение 64-128 Mb (8192-16384).

temp_buffers

Это размер буфера под временные объекты (временные таблицы). Среднее значение 2-4% всего количества RAM

Например, при 1-2 Gb RAM на сервере, достаточно указать в этом параметре значение 32-64 Mb.

work_mem

Это размер памяти, используемый для сортировки и кэширования таблиц.

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

Еще два важных параметра это maintenance_work_mem (для операций VACUUM, CREATE INDEX и других) и max_stack_depth

Примеры оптимальных настроек:

  • CPU: E3-1240 v3 @ 3.40GHz
  • RAM: 32Gb 1600Mhz
  • Диски: Plextor M6Pro

postgresql.conf:

  • shared_buffers = 8GB
  • work_mem = 128MB
  • maintenance_work_mem = 2GB
  • fsync = on
  • synchronous_commit = off
  • wal_sync_method = fdatasync
  • checkpoint_segments = 64
  • seq_page_cost = 1.0
  • random_page_cost = 6.0
  • cpu_tuple_cost = 0.01
  • cpu_index_tuple_cost = 0.0005
  • cpu_operator_cost = 0.0025
  • effective_cache_size = 24GB

Полезные запросы:

Блокировки БД по пользователям

Вывести все таблицы, размером больше 10 Мб


from pg_tables
where tableName not like ‘sql_%’ and pg_size_pretty(pg_total_relation_size(CAST(tablename as text))) like ‘%MB%’;

Определение размеров таблиц в базе данных PostgreSQL

Код SQL SELECT tableName, pg_size_pretty(pg_total_relation_size(CAST(tablename as text))) as size
from pg_tables
where tableName not like ‘sql_%’
order by size;

Пользователи блокирующие конкретную таблицу

Код SQL select a.usename, t.relname, a.current_query, mode from pg_locks l inner join pg_stat_activity a on a.procpid = l.pid inner join pg_stat_all_tables t on t.relid=l.relation where t.relname = ‘tablename’; Код SQL select relation::regclass, mode, a.usename, granted, pid from pg_locks l inner join pg_stat_activity a on a.procpid = l.pid where not mode = ‘AccessShareLock’ and relation is not null;

Запросы с эксклюзивными блокировками

Код SQL select a.usename, a.current_query, mode from pg_locks l inner join pg_stat_activity a on a.procpid = l.pid where mode ilike ‘%exclusive%’;

Количество блокировок по пользователям

Код SQL select a.usename, count(l.pid) from pg_locks l inner join pg_stat_activity a on a.procpid = l.pid where not(mode = ‘AccessShareLock’) group by a.usename;

Количество подключений по пользователям

Код SQL select count(usename), usename from pg_stat_activity group by usename order by count(usename) desc;

На данный момент производительность 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. Несмотря на то, что интерфейс на английском, он простой и интуитивно понятный. Думаю каждый желающий сможет с ним разобраться.

Я обещал написать о том, что в проектах с более менее серьезной нагрузкой БД либо помещается в память, либо не работает. Ситуация в современном мире меняется в связи с появлением 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 и из дискового кэша.