Оптимізуйте PostgreSQL для швидкого тестування


203

Я переходжу на PostgreSQL з SQLite для типового додатка Rails.

Проблема полягає в тому, що запущені характеристики стали повільними з PG.
На SQLite це зайняло ~ 34 секунди, на PG це ~ 76 секунд, що більш ніж в 2 рази повільніше .

Отже, тепер я хочу застосувати деякі методи, щоб привести продуктивність специфікацій нарівні з SQLite без модифікацій коду (в ідеалі просто шляхом встановлення параметрів з'єднання, що, мабуть, неможливо).

Пару очевидних речей з моєї голови:

  • Диск ОЗУ (добре було б побачити гарну установку з RSpec на OSX)
  • Неагреговані таблиці (чи можна застосувати її до всієї бази даних, щоб у мене не змінилися всі сценарії?)

Як ви, мабуть, зрозуміли, я не дбаю про надійність та інше (БД - це просто закид).
Мені потрібно максимально використати PG і зробити це так швидко, наскільки це можливо .

Найкраща відповідь в ідеалі описує хитрощі для виконання саме цього, налаштування та недоліки цих хитрощів.

ОНОВЛЕННЯ: fsync = off + full_page_writes = offлише зменшив час до ~ 65 секунд (~ -16 сек). Хороший старт, але далеко від цілі 34.

ОНОВЛЕННЯ 2: Я намагався використовувати диск RAM, але посилення продуктивності було в межах помилки. Тож, здається, цього не варто.

ОНОВЛЕННЯ 3: * Я знайшов найбільше вузьке місце і тепер мої характеристики працюють так само швидко, як і SQLite.

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

Щоб "виправити" його, я відкриваю транзакцію перед кожним тестом і повертаю її назад в кінці.

Деякі цифри для ~ 700 тестів.

  • Усечення: SQLite - 34s, PG - 76s.
  • Транзакція: SQLite - 17s, PG - 18s.

2x збільшення швидкості для SQLite. 4-кратне збільшення швидкості для PG.


2
Я дуже сумніваюся, що ви змусите його пройти так само швидко, як SQLite. SQLite з одним користувачем шалено швидко. Дизайн SQLite дуже швидкий з низьким числом користувачів та поганими масштабами; Дизайн Pg добре масштабується, але не такий швидкий для простої масової роботи лише з одним користувачем.
Крейг Рінгер

1
Я усвідомлюю це, але є певний випадок, який я сподіваюсь оптимізувати PG для (тестових циклів), щоб він був таким швидким, наскільки це можливо. Я не заперечую, щоб там було трохи повільніше, але 2.2x трохи надто повільно. Бачите, що я маю на увазі?
Дмитрій Нагірняк

+1 Мені будуть дуже цікаві оновлення щодо підходу до оперативної пам’яті, якщо у вас є якісь результати щодо цього.
цчо

@tscho Я обов'язково опублікую його тут. Але потрібен певний час, оскільки я працюю над іншими речами та "досліджую" речі PG на "тлі".
Дмитрій Нагірняк

чи вставляє дані ваша проблема чи запит ? З вашого запитання незрозуміло.
a_horse_with_no_name

Відповіді:


281

По-перше, завжди використовуйте останню версію PostgreSQL. Покращення продуктивності завжди приходить, тому ви, мабуть, витрачаєте свій час, якщо налаштовуєте стару версію. Наприклад, PostgreSQL 9.2 значно покращує швидкістьTRUNCATE і, звичайно, додає сканування, що стосуються лише індексу. Навіть незначні випуски завжди слід дотримуватися; див. політику щодо версій .

Не треба

Ви НЕ покласти табличного на Ramdisk або інший нетривалого зберігання .

Якщо ви втратите простір таблиць, вся база даних може бути пошкоджена і важка у використанні без значних робіт. Перевага в цьому порівняно з просто використанням UNLOGGEDтаблиць і з великою кількістю оперативної пам’яті для кешу в цьому випадку дуже мала .

Якщо ви справді хочете використовувати систему на базі ramdisk, initdbцілий новий кластер на ramdisk, initdbвикористовуючи новий екземпляр PostgreSQL на ramdisk, тож у вас є повністю одноразовий екземпляр PostgreSQL.

Конфігурація сервера PostgreSQL

Під час тестування ви можете налаштувати ваш сервер на нетривалу, але більш швидку роботу .

Це одне з єдиних прийнятних застосувань для fsync=offналаштування в PostgreSQL. Цей параметр в значній мірі говорить PostgreSQL не турбуватися із замовленим записом або будь-яким іншим неприємним захистом цілісності даних та безпекою аварій, що дає йому змогу повністю втратити ваші дані, якщо ви втратите електроенергію або збилися ОС.

Потрібно говорити, що ви ніколи не вмикаєте fsync=offу виробництві, якщо ви не використовуєте Pg як тимчасову базу даних для даних, які ви можете знову генерувати з інших місць. Якщо і тільки якщо ви робите, щоб вимкнути функцію fsync, також можна full_page_writesвимкнути, оскільки це вже не приносить користі. Остерігайтеся цього fsync=offі full_page_writesзастосовуйте їх на рівні кластера , щоб вони впливали на всі бази даних у вашому екземплярі PostgreSQL.

Для виробничого використання ви, можливо, можете використовувати synchronous_commit=offта встановити значення commit_delay, оскільки ви отримаєте багато тих же переваг, що й fsync=offбез гігантського ризику пошкодження даних. У вас є невелике вікно втрати останніх даних, якщо ви вмикаєте асинхронну передачу - але це все.

Якщо у вас є можливість трохи змінити DDL, ви також можете використовувати UNLOGGEDтаблиці в Pg 9.1+, щоб повністю уникнути журналу WAL та отримати реальний приріст швидкості за рахунок стирання таблиць у випадку збою сервера. Немає опції конфігурації, щоб зробити всі таблиці незаблокованими, вона повинна бути встановлена ​​під час CREATE TABLE. Окрім того, що ви корисні для тестування, це зручно, якщо у вашій базі даних є повні генерованих або неважливих даних, які в іншому випадку містять речі, які вам потрібно бути безпечними.

Перевірте свої журнали і побачите, чи отримуєте ви попередження про занадто багато контрольних пунктів. Якщо ви є, вам слід збільшити ваші контрольні_сегменти . Ви також можете налаштувати контрольну точку_комплектування_цілі, щоб згладити її.

Налаштуйтеся, shared_buffersщоб відповідати вашому навантаженню. Це залежить від ОС, залежить від того, що ще відбувається з вашою машиною, і вимагає деяких проб і помилок. Значення за замовчуванням надзвичайно консервативні. Можливо, вам доведеться збільшити максимальний ліміт спільної пам'яті ОС, якщо ви збільшуєтесь shared_buffersна PostgreSQL 9.2 і нижче; 9.3 і вище змінили те, як вони використовують спільну пам'ять, щоб уникнути цього.

Якщо ви використовуєте лише пару з’єднань, які роблять багато роботи, збільште їх, work_memщоб дати їм більше оперативної пам’яті, щоб грати для різного роду тощо. Остерігайтеся, що занадто висока work_memнастройка може спричинити проблеми із пам'яттю, оскільки це не так за з'єднання, тому один запит може мати багато вкладених типів. Збільшити вас дійсно доведеться лише в тому work_memвипадку, якщо ви можете побачити сортування, що проливаються на диск EXPLAINабо ввійшли в систему з log_temp_filesналаштуваннями (рекомендовано), але більш високе значення також може дати Pg вибрати розумніші плани.

Як сказав інший плакат, тут розумно розміщувати xlog та основні таблиці / індекси на окремих жорстких дисках, якщо це можливо. Окремі розділи є досить безглуздим, вам дуже потрібні окремі диски. Такий поділ має набагато меншу користь, якщо ви працюєте з, fsync=offі майже немає, якщо використовуєте UNLOGGEDтаблиці.

Нарешті, налаштуйте свої запити. Переконайтеся, що ваша random_page_costта seq_page_costвідображає продуктивність вашої системи, переконайтеся, що ви effective_cache_sizeправильні тощо. Використовуйте EXPLAIN (BUFFERS, ANALYZE)для вивчення окремих планів запитів та ввімкніть auto_explainмодуль, щоб повідомити про всі повільні запити. Ви можете часто покращити ефективність запитів, просто створивши відповідний індекс або налаштувавши параметри вартості.

AFAIK немає способу встановити цілу базу даних або кластер як UNLOGGED. Цікаво було б це зробити. Розгляньте запитання у списку розсилки PostgreSQL.

Налаштування ОС хоста

Ви також можете виконати налаштування на рівні операційної системи. Головне, що ви можете зробити, це переконати операційну систему не змивати записи на диск агресивно, оскільки вам насправді все одно, коли / якщо вони змусять його на диск.

У Linux ви можете контролювати це з підсистемою віртуальної пам'яті «сек dirty_*настройки, як dirty_writeback_centisecs.

Єдине питання, коли налаштування запису для зворотного зв'язку буде занадто слабким, полягає в тому, що флеш якоїсь іншої програми може призвести до того, що всі накопичені буфери PostgreSQL також будуть змиті, що спричинить великі зупинки, поки все блокується на записі. Ви можете полегшити це, запустивши PostgreSQL в іншій файловій системі, але деякі помилки можуть бути на рівні пристрою або на цілому хості, а не на рівні файлової системи, тому ви не можете на це покладатися.

Ця настройка дійсно вимагає розібратися з налаштуваннями, щоб побачити, що найкраще підходить для вашої роботи.

На нових ядрах ви можете переконатися, що vm.zone_reclaim_modeвін встановлений на нулі, оскільки це може спричинити серйозні проблеми з роботою з системами NUMA (більшість систем сьогодні) через взаємодію з тим, як управляє PostgreSQL shared_buffers.

Налаштування запитів та навантаження

Це речі, які дійсно потребують змін коду; вони можуть вам не підходити. Деякі речі ви можете застосувати.

Якщо ви не займаєтеся великими операціями, почніть. Багато дрібних трансакцій коштують дорого, тому вам слід купувати речі, коли це можливо та практично. Якщо ви використовуєте команду async, це менш важливо, але все-таки настійно рекомендується.

По можливості використовуйте тимчасові таблиці. Вони не генерують WAL-трафік, тому вони набагато швидші для вставок та оновлень. Іноді варто притискати купу даних до тимчасової таблиці, маніпулювати нею, проте потрібно, а потім зробити INSERT INTO ... SELECT ...копіювати її до підсумкової таблиці. Зауважте, що тимчасові таблиці проводяться за сеансом; якщо ваш сеанс закінчується або ви втрачаєте зв’язок, тоді таблиця темп відключається, і жодне інше з'єднання не може бачити вміст темп-таблиць сеансів.

Якщо ви використовуєте PostgreSQL 9.1 або новішу версію, ви можете використовувати UNLOGGEDтаблиці для даних, які ви можете дозволити втратити, як-от стан сеансу. Вони видно на різних сесіях і зберігаються між з'єднаннями. Вони врізаються, якщо сервер закривається нечисто, тому їх не можна використовувати для нічого, що ви не можете створити заново, але вони чудово підходять для кешів, матеріалізованих подань, таблиць стану тощо.

Загалом, не варто DELETE FROM blah;. Використовувати TRUNCATE TABLE blah;замість цього; це набагато швидше, коли ви скидаєте всі рядки в таблицю. Обріжте багато таблиць за один TRUNCATEдзвінок, якщо можете. Існує застереження, якщо ви робите багато TRUNCATESмаленьких столиків знову і знову; див.: Швидкість усікання Postgresql

Якщо у вас немає індексів зовнішніх ключів, DELETEвключення первинних ключів, на які посилаються ці іноземні ключі, буде жахливо повільним. Не забудьте створити такі індекси, якщо ви коли-небудь очікуєте, що DELETEце згадана таблиця (и). Індекси не потрібно для TRUNCATE.

Не створюйте індекси, які вам не потрібні. Кожен індекс має вартість обслуговування. Спробуйте використовувати мінімальний набір індексів, і дозвольте скануванню растрових індексів поєднувати їх, а не підтримувати занадто багато величезних, дорогих багатоколонкових індексів. Там, де потрібні індекси, спробуйте спочатку заповнити таблицю, а потім створити індекси в кінці.

Обладнання

Маючи достатньо оперативної пам’яті, щоб вмістити всю базу даних, це величезний виграш, якщо ви зможете керувати нею.

Якщо вам не вистачає оперативної пам’яті, тим швидше ви можете зберігати місця. Навіть дешевий SSD робить величезну різницю в порівнянні з прядильною іржею. Не довіряйте дешевим SSD для виробництва, хоча вони часто не є безпечними і можуть з'їсти ваші дані.

Навчання

Книга Грега Сміта, PostgreSQL 9.0 High Performance залишається актуальною, не дивлячись на дещо старішу версію. Це має бути корисною довідкою.

Приєднуйтесь до загального списку розсилки PostgreSQL і дотримуйтесь його.

Читання:


10
Я також можу порекомендувати PostgreSQL 9.0 High Performance від @GregSmith, це справді чудове читання. Книга охоплює всі аспекти настройки продуктивності від компонування диска до налаштування запитів і дає вам дуже добре розуміння внутрішніх питань PG.
цчо

10
Я не випустив оновлення книги для PostgreSQL 9.1, єдиного випуску після її публікації, тому що в 9.1 не було достатньо змін, пов'язаних з продуктивністю, щоб гарантувати це.
Грег Сміт

3
Відмінний запис. Як і невелике оновлення, "Вам може знадобитися збільшити максимальний об'єм спільної пам'яті ОС, якщо ви збільшите спільні_буфери" більше не відповідає дійсності (для більшості користувачів) в PostgreSQL 9.3: postgresql.org/docs/9.3/static/release-9- 3.html # AEN114343
Gunnlaugur Briem

1
@brauliobo Мої тести часто роблять багато TX при високій TPS ... тому що я намагаюся імітувати виробництво, включаючи великі попутні робочі навантаження. Якщо ви маєте на увазі "єдине підключення, лінійне тестування", то я погодився б з вами.
Крейг Рінгер

1
stackoverflow.com/questions/11419536/… DELETE може бути швидшим, ніж TRUNCATE для таблиць з кількома рядками, що, ймовірно, має місце в тестах.
Джонатан Кросмер

9

Використовуйте інший макет диска:

  • інший диск для $ PGDATA
  • інший диск для $ PGDATA / pg_xlog
  • різний диск для тем-файлів (на базу даних $ PGDATA / база // pgsql_tmp) (див. примітку про work_mem)

postgresql.conf налаштування:

  • shared_memory: 30% доступної оперативної пам’яті, але не більше 6–8 ГБ. Схоже, краще мати менше спільної пам’яті (2 Гб - 4 ГБ) для інтенсивного навантаження для запису
  • work_mem: здебільшого для обраних запитів із сортами / агрегаціями. Це за налаштуваннями з'єднання, і запит може виділити це значення кілька разів. Якщо дані не підходять, використовується диск (pgsql_tmp). Поставте прапорець "Пояснити аналіз", щоб побачити, скільки пам'яті вам потрібно
  • fsync та sinkronous_commit: Значення за замовчуванням є безпечними, але якщо ви можете терпіти втрачені дані, ви можете вимкнути, а потім вимкнути
  • random_page_cost: якщо у вас SSD або швидкий масив RAID, ви можете знизити це до 2,0 (RAID) або навіть нижче (1,1) для SSD
  • checkpoint_segments: ви можете перейти на 32 або 64 і змінити checkpoint_completion_target на 0,9. Менше значення дозволяє швидше відновити після аварії

4
Зауважте, що якщо ви вже працюєте fsync=off, розміщення pg_xlog на окремому диску вже не покращиться.
intgr

Значення 1,1 для SSD здається дуже некваліфікованим. Я визнаю, що це те, що деякі професіонали сліпо рекомендували. Навіть SSD є значно швидшими для послідовного зчитування, ніж випадкові читання.
Acumenus

@ABB Так, але у вас також є ефекти кешування буфера ОС на роботі. Усі ці парами все одно трохи рукою ...
Крейг Рінгер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.