23 додаткових способів прискорити Firebird
Олексій Ковязін, IBSurgeon, [email protected], 08-січ-2019
Переклади: Португальська
Чому «ще 23»?
Деякі з вас пам’ятають статтю «45 способів прискорити Firebird», опубліковану в травні 2016 року. Тепер настав час опублікувати наступну серію порад і підказок, що переважно ґрунтуються на досвіді оптимізації та обслуговування баз даних Firebird і серверів із великою кількістю підключень (1000+).
1. Установіть схему електроживлення «Висока продуктивність» у Windows Server 2016 та 2019
За замовчуванням Windows Server має план живлення «Збалансований», який не підходить для серверів баз даних. Установіть «Висока продуктивність» і отримайте приблизно +20% продуктивності для операцій, інтенсивних до CPU. Це можна зробити онлайн, без перезавантаження. На малюнку нижче показано графік CPU, який демонструє перевагу плану «Висока продуктивність»:

Більше деталей про наші тести з планами живлення Windows можна знайти тут.
2. Увімкніть «Взаємодія з робочим столом» для Classic на Windows
Якщо ви використовуєте Firebird з архітектурою Classic на Windows, увімкніть позначку «Дозволити службі взаємодіяти з робочим столом». Без цього налаштування ресурс «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) за допомогою наступної команди:
cat /proc//limits
і зверніть увагу на рядок із максимальною кількістю відкритих файлів.
Firebird може використовувати до 4 дескрипторів на одне підключення, і якщо ви бачите щось подібне:
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% оперативної пам’яті для файлового кешу на Windows
Менеджер пам’яті ОС має наслідки щодо розподілу пам’яті, і за замовчуванням Windows вимагає 40% оперативної пам’яті для файлового кешу.
На жаль, поганий інструмент Windows Task Manager показує пам’ять, яка використовується для файлового кешу, як «вільну», і деякі адміністратори намагаються змусити Firebird споживати всю цю вільну пам’ять, тому вони встановлюють дуже високі значення параметра DefaultDBCachePage у firebird.conf, що зазвичай призводить до свопінгу.
Завжди використовуйте інструмент RAMMap, щоб бачити фактичне використання пам’яті на Windows.
Емпіричне правило для Windows Server (виділеного для використання як сервер Firebird) таке: пам’ять Firebird (Working Set) має бути меншою за 40% від загальної оперативної пам’яті. Якщо загальний розмір робочих наборів для всіх процесів перевищує 50%, Windows може почати свопінг.
Зверніть увагу: «резервувати» тут означає не лише «не встановлювати занадто багато буферів сторінок у Firebird», але також, що важливо, обмежити використання пам’яті іншим програмним забезпеченням. Наприклад, якщо у вас MS Exchange або MSSQL на тому самому сервері з Firebird, переконайтеся, що ви обмежили їхні апетити до пам’яті.
Якщо вам цікаво дізнатися деталі, я записав вебінар, присвячений управлінню пам’яттю у Firebird:
- Частина 1. https://www.youtube.com/watch?v=ZBmLgbYt4aM
- Частина 2. https://www.youtube.com/watch?v=-1.DF2FnU-A
7. Зарезервуйте 30% оперативної пам’яті для файлового кешу на Linux
Linux працює з файловим кешем інакше, ніж Windows, і загалом обсяг оперативної пам’яті, який використовується для файлового кешу, може бути значно меншим, ніж на Windows, без помітної деградації продуктивності Firebird. Однак, щоб гарантувати високу продуктивність системи з великою кількістю підключень, особливо на Classic і SuperClassic, гарною ідеєю буде зарезервувати 30% оперативної пам’яті для файлового кешу.
8. Використовуйте irqbalance на Linux
irqbalance часто покращує продуктивність 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 (також званий «буфери сторінок») задається параметром DefaultDBCachePages у firebird.conf/databases.conf або безпосередньо в заголовку бази даних.
У Firebird 3 SuperServer розмір цього кешу можна встановити дуже великим, але важливо пам’ятати про інший параметр: FileSystemCacheThreshold.
Якщо FileSystemCacheThreshold менший за DefaultDBCachePages або буфери сторінок, файловий кеш операційної системи не використовуватиметься, що може призвести до проблем із продуктивністю.
У 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 для бази безпеки - невеликий ризик пошкодження у цьому випадку не є проблемою.
Найрадикальніший спосіб - зробити базу безпеки лише для читання - це усуне всі записи до неї.
Якщо ви не часто змінюєте користувачів у базі безпеки, це найкраще рішення.
14. Спробуйте SuperClassic на Firebird 3
У Firebird 3 архітектура SuperServer активно рекламувалася як ultimate-рішення для продуктивності, але існують типи навантаження, які демонструють кращу продуктивність із SuperClassic (але не Classic - він завжди працює повільніше, ніж SuperServer/SuperClassic).
Як безпечно провести цей експеримент? Виконайте наведені нижче кроки:
Щоб спробувати SuperClassic
- Встановіть у firebird.conf
- ServerMode=SuperClassic
- DefaultDbCachePages=1024
- gfix -buff 0
- Перезапустіть Firebird
Щоб повернутися до SuperServer
- Встановіть у firebird.conf
- ServerMode=SuperServer
- DefaultDbCachePages=N # N*розмір сторінки*кількість_баз < 25% RAM
- FileSystemCacheThreshold = N+1
- gfix -buff 0
- Перезапустіть Firebird
Будь ласка, напишіть мені ([email protected]) про результати експерименту, мені цікаво побачити результати.
15. Велика база даних? Збільште розмір сторінки
За замовчуванням бази даних Firebird мають такі розміри сторінок:
- 2.5 - 4096 байт
- 3.0 - 8192 байт
Однак максимальний розмір сторінки - 16K (у 4.0 - 32K).
Для баз даних понад 100 ГБ у 95% випадків краще мати максимально доступний розмір сторінки, щоб:
- Зменшити глибину індексів. Рекомендується мати індекси з глибиною менше або рівною 3. Індекси з глибиною 4 і 5 будуть набагато повільнішими
- Підвищити використання RAM. Кеш Firebird вказується у сторінках, 1000 сторінок із розміром 8K становитимуть 8 МБ фактичної пам’яті, а з 16K - 16 МБ.
- Зменшити кількість системних сторінок. Це прискорить доступ до записів великих таблиць (менше переходів покажчик-покажчик-сторінка даних) і допоможе з підготовкою великих 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 у виводі
gstat -h database
Як вимкнути:
gfix -use reserve database
Після цієї команди нові сторінки даних створюватимуться із зарезервованим простором.
Однак, щоб досягти повного ефекту, необхідно створити резервну копію бази даних за допомогою gbak, а потім відновити - у цьому випадку всі сторінки даних будуть із зарезервованим простором.
Зверніть увагу: розмір бази даних зросте після видалення прапорця no_reserve та резервного копіювання/відновлення.
17. Встановіть великий початковий розмір для lock table Firebird
Lock table - це механізм Firebird, який використовується для синхронізації доступу до внутрішніх об’єктів рушія.
Lock table Firebird може зростати автоматично, але її збільшення - це повільна операція, яка може призвести до мікрозатримок. Lock table може лише зростати, починаючи з початкового розміру (він встановлюється у firebird.conf).
Щоб запобігти багаторазовим циклам збільшення lock table, гарною ідеєю буде спостерігати за розміром lock table наприкінці робочого періоду (день, тиждень тощо), а потім встановити його як початковий розмір у firebird.conf.
LockMemSize=99999999
Для довідки: LockMemSize у системах із високим навантаженням із ~1000 користувачів зазвичай нижче 200 МБ.
18. Використовуйте fb_lock_print для підрахунку кількості підключень до бази даних
Отримання кількості підключень до бази даних - часте завдання для розробників баз даних: це може бути необхідним для ліцензування, наприклад.
Часто розробники використовують запит SELECT count(*) FROM MON$ATTACHMENTS, щоб отримати це значення, але це не оптимальний спосіб: часті запити до таблиць MON$ можуть бути навантаженням для бази даних, тому краще використовувати альтернативу:
Виконайте
fb_lock_print -d назва_бази_даних | 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() лише для перевірки існування запису.
Наступний запит прочитає всі записи відповідно до умови1:
(select count(*)…. where condition11) >0
Краще використовувати таку конструкцію:
Exists(select first 1 id where condition1)
Якщо умова1 повертає більше ніж 1 запис, запропонований варіант буде набагато швидшим, оскільки він не читає всі записи, а зупиняється після першого отриманого запису.
21. Уникайте непотрібного сортування у збережених процедурах
Упорядкування результатів запиту всередині збереженої процедури має бути виправдане бізнес-логікою.
Наприклад, у прикладі збереженої процедури нижче пункт ORDER BY є марним з точки зору бізнес-логіки, але він додає непотрібну операцію сортування.
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, за замовчуванням він становить 64 МБ.
Навіть із збільшеним TempCacheLimit довготривалі запити з великою кількістю відсортованих записів зрештою споживуть весь виділений обсяг, і в результаті сортування перейде до тимчасових файлів (тобто на диск). Це може призвести до значного сповільнення.
Рекомендація: своєчасно закривайте всі такі запити.
Питання?
Не соромтеся зв’язатися зі мною з будь-якими питаннями: [email protected]!