Цю сторінку перекладено машинним перекладом. Читайте англійський оригінал. English

Бібліотека IBSurgeon

23 додаткових способів прискорити Firebird

Олексій Ковязин, IBSurgeon, [email protected], 08-Jan-2019

Переклади: Португальська

Чому “ще 23”?

Деякі з вас пам’ятають статтю «45 способів прискорити Firebird», яка була опублікована в травні 2016 року. Тепер настав час опублікувати наступну серію порад і прийомів, переважно заснованих на досвіді оптимізації та обслуговування баз даних і серверів Firebird із великою кількістю з’єднань (1000+).

1. Встановіть параметри живлення на високу продуктивність у Windows Server 2016 і 2019

За замовчуванням у Windows Server схема живлення встановлена на “Balanced” (Збалансована), що не підходить для серверів баз даних. Встановіть її на “High Performance” (Висока продуктивність) і отримайте приблизно +20% продуктивності для операцій, інтенсивних щодо CPU. Це можна зробити онлайн, без перезапуску чи перезавантаження. На зображенні нижче показано графік CPU, який демонструє перевагу схеми живлення “High-performance”:

Детальніше про наші тести зі схемами живлення Windows можна дізнатися тут.

2. Увімкніть «Interact with desktop» для Classic у Windows

Якщо ви використовуєте Firebird з архітектурою Classic у Windows, увімкніть прапорець «Allow service to interact with desktop» (Дозволити службі взаємодіяти з робочим столом). Без цього налаштування ресурс «desktop heap» обмежується Windows, і Firebird не може відкрити більше ніж 250-300 з’єднань (залежить від метаданих бази даних і пов’язаного споживання пам’яті) - виникне помилка Out Of Memory.

3. Обережно: контролер домену

Проблема в тому, що Windows із роллю контролера домену вимикає кеш запису на диску з базою даних Active Directory.

Це впливає на Firebird різними способами (як і на інші застосунки, звісно), і він демонструє значно гіршу продуктивність, ніж на серверах без ролей Active Directory.

Зверніть увагу, що ця проблема стосується такої популярної версії Windows, як Windows Small Business Server 2011, а також інших версій із DC.

4. Збільште ліміт «max open files» у Linux

Якщо ви використовуєте Linux як сервер бази даних, не забудьте налаштувати ліміти для Firebird. Перевірте ліміти для вашого процесу Firebird (SuperServer або SuperClassic) такою командою:

Code
cat /proc//limits

і зверніть увагу на рядок із максимальною кількістю відкритих файлів.

Firebird може використовувати до 4 дескрипторів на з’єднання, і якщо у вас щось на кшталт цього:

Code
Max open files 4096 4096 files

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

Зверніть увагу - якщо у вас на сервері 4 бази даних, з’єднання для кожної бази даних враховується.

Встановіть більше - я рекомендую 65535.

Не забудьте перевірити ще раз після перезапуску процесу Firebird: чи було це застосовано чи ні.

Для архітектури Classic необхідно перевірити та збільшити ліміти для користувача «firebird».

5. Використовуйте сучасний Linux

Так, я розумію, що ця порада тривіальна, але я багато разів бачив значне покращення продуктивності після міграції з CentOS 6 на 7, з Ubuntu 12 на 16 (на тому самому обладнанні!), тож тепер це обов’язкова рекомендація для серверів баз даних із понад 250-300 з’єднаннями. Сучасний Linux є передумовою для подальших кроків оптимізації.

Рекомендовані версії Linux: CentOS 7.x та Ubuntu 16, 18.

6. Зарезервуйте 40% RAM для файлового кешу у Windows

Менеджер пам’яті ОС має особливості щодо розподілу пам’яті, і за замовчуванням Windows вимагає 40% RAM для файлового кешу.

На жаль, поганий інструмент Windows Task Manager показує пам’ять, яка використовується для файлового кешу, як «вільну», і деякі адміністратори намагаються змусити Firebird споживати всю цю вільну пам’ять, тому вони встановлюють параметр DefaultDBCachePage у firebird.conf на дуже високі значення, і це зазвичай призводить до свопінгу.

Завжди використовуйте інструмент RAMMap, щоб побачити фактичне використання пам’яті у Windows.

Емпіричне правило для Windows Server (виділеного для використання як сервер Firebird) таке: пам’ять Firebird (Working Set) має бути меншою за 40% від загальної RAM. Якщо загальний розмір робочих наборів для всіх процесів перевищує 50%, Windows може запустити своп.

Зверніть увагу: “зарезервувати” тут означає не лише “не встановлювати занадто багато буферів сторінок у Firebird”, а й, що також важливо, обмежити використання пам’яті іншим програмним забезпеченням. Наприклад, якщо у вас MS Exchange або MSSQL на тому самому сервері, що й Firebird, обов’язково обмежте їхній апетит до пам’яті.

Якщо вам цікаво дізнатися деталі, я записав вебінар, присвячений управлінню пам’яттю у Firebird:

7. Зарезервуйте 30% RAM для файлового кешу у Linux

Linux працює з файловим кешем інакше, ніж Windows, і, загалом, обсяг RAM, що використовується для файлового кешу, може бути значно меншим, ніж у Windows, без помітного погіршення продуктивності Firebird. Однак, щоб гарантувати високу продуктивність системи з великою кількістю з’єднань, особливо на Classic і SuperClassic, гарною ідеєю буде зарезервувати 30% RAM для файлового кешу.

8. Використовуйте irqbalance у Linux

irqblalnce часто покращує продуктивність Firebird і балансування навантаження CPU на серверах із великою кількістю ядер.

9. Для віртуальних машин - обережно з Memory Overcommit

Віртуальну машину можна налаштувати так, щоб вона мала більше пам’яті, ніж фізично існує на хост-машині - за допомогою функції, відомої як Memory Overcommit (назва може відрізнятися в різних системах віртуалізації). Це означає, що в разі піку споживання пам’яті (на VM із сервером бази даних або на сусідній VM) може запуститися своп, що призведе до значних затримок. Для високопродуктивної VM, призначеної для сервера бази даних, уся пам’ять має бути статичною.

10. Для віртуальних машин - перевірте ліміти VM

Часто VM створюються з типовими лімітами CPU та IO, які можуть бути дуже низькими, наприклад 50 IOPS і 10% CPU. Перевірте налаштування вашої серверної VM і зніміть будь-які ліміти - високопродуктивний сервер бази даних повинен мати всі можливі CPU, пропускну здатність та IO.

11. Очищуйте тимчасові файли Firebird

Firebird створює багато тимчасових файлів для різних операцій: сортування, обробки BLOB, трасування. Ці файли зберігаються в таких місцях: у Windows C:\ProgramData\firebird, у Linux / tmp / firebird

Зазвичай ці файли мають очищатися автоматично, однак іноді цього не відбувається (наприклад, у разі перезавантаження сервера).

Періодично перевіряйте ці папки та очищуйте старі файли - там можуть бути багато ГБ застарілих файлів fb_NNN, і їх очищення звільнить місце на системному диску.

12. Не забудьте увімкнути файловий кеш із великим кешем Firebird

Як ви знаєте, кеш Firebird (також званий «page buffers») задається параметром DefaultDBCachePages у firebird.conf/databases.conf або безпосередньо в заголовку бази даних.

У Firebird 3 SuperServer розмір цього кешу можна встановити дуже великим, але важливо пам’ятати про інший параметр: FileSystemCacheThreshold.

Якщо FileSystemCacheThreshold менший за DefaultDBCachePages або page buffers, файловий кеш операційної системи не буде використовуватися, що може призвести до проблем із продуктивністю.

У 99% випадків краще мати ввімкнений файловий кеш.

Щоб це забезпечити, завжди встановлюйте параметри згідно з таким правилом:

  • DefaultDBCachePages = X
  • FileSystemCacheThreshold = X+ N, N>1

Є рідкісні випадки, коли вимкнення файлового кешу покращує продуктивність - якщо у вас є такий приклад, будь ласка, зв’яжіться зі мною - [email protected]!

13. Прискорте базу даних безпеки

Кожне з’єднання з базою даних Firebird встановлює з’єднання з базою даних безпеки (security3.fdb у випадку Firebird 3) і виконує кілька читань і записів (сторінки транзакцій, заголовна сторінка). Якщо у вас часті з’єднання, продуктивність вашої бази даних безпеки може стати проблемою.

Як мінімум, ви можете зробити таке:

  • Збільшити page buffers для securityN.fdb (емпіричний оптимум — 256 буферів)
  • Перемістити security3.fdb на швидкий диск (це стандартна можливість у Firebird 3, у 2.5 це потребуватиме перевстановлення)

Потім ви можете встановити Forced Writes OFF для бази даних security — невелика ймовірність пошкодження в цьому випадку не є проблемою.

Найрадикальніший спосіб — зробити базу даних security доступною лише для читання — це усуне всі записи до неї.

Якщо ви не часто змінюєте користувачів у базі даних security, це найкраще рішення.

14. Спробуйте SuperClassic на Firebird 3

У Firebird 3 архітектуру SuperServer активно рекламували як остаточне рішення для продуктивності, але є деякі типи навантаження, які демонструють кращу продуктивність із SuperClassic (але не Classic — він завжди працює повільніше, ніж SuperServer/SuperClassic).

Як провести цей експеримент безпечним способом? Виконайте наведені нижче кроки:

Щоб спробувати SuperClassic

  1. Встановіть у firebird.conf
  2. ServerMode=SuperClassic
  3. DefaultDbCachePages=1024
  4. gfix -buff 0
  5. Перезапустіть Firebird

Щоб повернутися до SuperServer

  1. Встановіть у firebird.conf
  2. ServerMode=SuperServer
  3. DefaultDbCachePages=N # N*page size*databases_count < 25% RAM
  4. FileSystemCacheThreshold = N+1
  5. gfix -buff 0
  6. Перезапустіть Firebird

Будь ласка, напишіть мені ([email protected]) про результати експерименту, мені цікаво побачити результати.

15. Велика база даних? Збільште розмір сторінки

За замовчуванням бази даних Firebird мають такі розміри сторінок:

  • 2.5 - 4096 байтів
  • 3.0 - 8192 байтів

Однак максимальний розмір сторінки — 16K (у 4.0 — 32K).

Для баз даних понад 100Gb у 95% випадків краще мати найбільший доступний розмір сторінки, щоб:

  • Зменшити глибину індексів. Рекомендується мати індекси з глибиною менше або рівною 3. Індекси з глибиною 4 і 5 будуть значно повільнішими
  • Збільшити використання RAM. Кеш Firebird задається в сторінках, 1000 сторінок із розміром сторінки 8K становитимуть 8Mb фактичної пам’яті, а з 16K — 16Mb.
  • Зменшити кількість системних сторінок. Це прискорить доступ до записів великих таблиць (менше переходів покажчик-покажчик-сторінка даних), а також допоможе з підготовкою великих SQL-запитів. Щоб збільшити розмір сторінки бази даних, базу даних слід зробити резервну копію за допомогою інструмента gbak, а потім відновити з параметром -page ( gbak -c -page 16384).

Зверніть увагу: якщо у вас є база даних із багатьма малими blob-ами, збільшення розміру сторінки може як зменшити фрагментацію, так і збільшити її, і важко передбачити, чи підвищить це продуктивність, чи знизить її.

16. Не використовуйте прапорець no_reserve

Прапорець no_reserve змушує Firebird не резервувати вільний простір (30%) на сторінках даних для можливих версій записів, які виникають після UPDATE або DELETE. Цей прапорець дозволяє зберігати дані більш компактно (і розмір бази даних також менший), але у разі UPDATE/DELETE всі зміни потрапляють на нову сторінку даних. Як результат, у базі даних із прапорцем no_reserve операції UPDATE/DELETE повільніші.

Отже, якщо ваша база даних не доступна лише для читання, я рекомендую видалити прапорець no_reserve.

Як перевірити, чи він встановлений — дивіться рядок Attributes у виводі

Code
gstat -h database

Як вимкнути:

Code
gfix -use reserve database

Після цієї команди нові сторінки даних створюватимуться із зарезервованим простором.

Однак, щоб досягти повного ефекту, необхідно зробити резервну копію бази даних за допомогою gbak, а потім відновити, у цьому випадку всі сторінки даних будуть із зарезервованим простором.

Зверніть увагу: розмір бази даних зросте після видалення no_reserve прапорця та backup/restore.

17. Встановіть високий початковий розмір для таблиці блокувань Firebird

Таблиця блокувань — це механізм Firebird, який використовується для синхронізації доступу до внутрішніх об’єктів рушія.

Таблиця блокувань Firebird може збільшуватися автоматично, але її збільшення — це повільна операція, яка може призводити до мікро-зависань. Таблиця блокувань може лише зростати, починаючи з початкового розміру (він задається в firebird.conf).

Щоб запобігти багаторазовим циклам збільшення таблиці блокувань, гарною ідеєю буде спостерігати за розміром таблиці блокувань наприкінці робочого періоду (день, тиждень тощо), а потім встановити його як початковий розмір у firebird.conf.

LockMemSize=99999999

Для довідки: LockMemSize у системах із високим навантаженням і ~1000 користувачів зазвичай становить менше 200Mb.

18. Використовуйте fb_lock_print для підрахунку кількості з’єднань із базою даних

Отримання кількості з’єднань із базою даних — часте завдання для розробників баз даних: це може бути необхідно, наприклад, для цілей ліцензування.

Часто розробники використовують запит SELECT count(*) FROM MON$ATTACHMENTS, щоб отримати це значення, але це не оптимальний спосіб: часті запити до таблиць MON$ можуть бути навантаженням для бази даних, тому краще використовувати альтернативу:

Виконайте

fb_lock_print -d database_name | alias

і перевірте значення Owners — воно покаже поточну кількість з’єднань із базою даних.

19. Уникайте непотрібних LEFT JOIN

Часто я бачу запити з такою конструкцією:

T1 LEFT JOIN T2 ON (…) WHERE T2.Field_condition

По суті, умова на T2 виключає NULL-и з виводу LEFT JOIN T2, тому можна змінити LEFT JOIN на INNER JOIN — це не вплине на результат запиту.

INNER JOIN дає більше свободи оптимізатору Firebird, і в сучасних версіях Firebird він оптимізується значно краще, ніж LEFT.

Особливо це має сенс у таких випадках:

  • Немає умови для T1 у реченні WHERE
  • T2 — невелика таблиця

20. Уникайте непотрібного підрахунку записів

Ще одна поширена помилка у складних запитах до бази даних і збережених процедурах — використання select count() лише для перевірки існування запису.

Наступний запит прочитає всі записи відповідно до condition1:

Code
(select count(*)…. where condition11) >0

Краще використовувати цю конструкцію натомість

Code
Exists(select first 1 id where condition1)

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

21. Уникайте непотрібного сортування у збережених процедурах

Упорядкування результатів запиту всередині збереженої процедури має бути обґрунтоване бізнес-логікою.

Наприклад, у наведеному нижче прикладі збереженої процедури речення ORDER BY є марним з точки зору бізнес-логіки, але воно додає непотрібну операцію сортування.

Code
create or alter procedure NEW_PROCEDURE
returns (
    SUMX double precision)
as
declare variable _amount double precision;
begin
for select T1.amount from Table1 t1 where ....
    order by id
    into :_amount
    do
    begin
     sumx=sumx+_amount
    end;
  suspend;
end

Перевірте свій код PSQL на подібні ситуації та видаліть марний ORDER BY (а також distinct і UNION).

22. Не тримайте запити в підготовленому стані без необхідності

Часто ми бачимо 500-1000 підготовлених речень у кожному з’єднанні (це можна перевірити за допомогою запитів MON$).

Переважна більшість із них виконується лише один раз, а потім вони просто лежать у RAM, збільшуючи робочий набір Firebird і сповільнюючи запити MON$.

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

23. Завжди закривайте запити з великим сортуванням

Доки SQL-запит із сортуванням (ORDER BY, GROUP BY, UNION, distinct) не закрито, Firebird утримує відсортовані записи в пам’яті. Розмір пам’яті, виділеної для сортування, задається параметром TempCacheLimit у firebird.conf, за замовчуванням він становить 64Mb.

Навіть із збільшеним TempCacheLimit довготривалі запити з великою кількістю відсортованих записів зрештою споживатимуть усю виділену кількість, і як результат, сортування перейде до тимчасових файлів (тобто на диск). Як результат, це може призвести до значного сповільнення.

Рекомендація — своєчасно закривати всі такі запити.

Питання?

Будь ласка, зв’яжіться зі мною з будь-якими питаннями: [email protected]!