Firebirdを高速化する23の追加方法
Alexey Kovyazin, IBSurgeon, [email protected], 2019年1月8日
翻訳: ポルトガル語
「23 more」とは?
2016年5月に公開された「Firebirdを高速化する45の方法」という記事を覚えている方もいるでしょう。今回は、主に接続数が多い(1000以上)Firebirdデータベースとサーバーの最適化・メンテナンスの経験に基づいた、次の一連のヒントとテクニックを公開する時期が来ました。
1. Windows Server 2016および2019で電源オプションを「高パフォーマンス」に設定する
デフォルトでは、Windows Serverの電源プランは「バランス」に設定されており、データベースサーバーには適していません。「高パフォーマンス」に設定すると、CPU負荷の高い操作で約+20%のパフォーマンス向上が得られます。再起動や再起動なしでオンラインで設定できます。下の図は、CPUグラフを示しており、「高パフォーマンス」電源プランの利点を示しています:

Windowsの電源プランに関するテストの詳細はこちらでご覧いただけます。
2. Windows版Classicで「デスクトップとの対話」を有効にする
WindowsでClassicアーキテクチャのFirebirdを使用している場合は、「サービスがデスクトップと対話できるようにする」チェックボックスを有効にしてください。この設定がないと、Windowsによってリソース「デスクトップヒープ」が制限され、Firebirdは250〜300接続(データベースのメタデータと関連するメモリ消費によって異なります)を超えて開くことができず、メモリ不足エラーが発生します。

3. 注意:ドメインコントローラー
Windowsにドメインコントローラーの役割があると、Active Directoryデータベースがあるディスクの書き込みキャッシュが無効になるという問題があります。
これはFirebirdにさまざまな形で影響を与え(もちろん他のアプリケーションにも)、Active Directoryの役割がないサーバーよりも大幅にパフォーマンスが低下します。
この問題は、Windows Small Business Server 2011などの人気のあるWindowsバージョンや、DCを持つ他のバージョンにも影響することに注意してください。
4. 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. Windowsでファイルキャッシュ用にRAMの40%を確保する
OSメモリマネージャーにはメモリ割り当てに関する影響があり、デフォルトではWindowsはファイルキャッシュにRAMの40%を必要とします。
残念ながら、Windowsタスクマネージャーはファイルキャッシュに使用されているメモリを「空き」として表示するため、一部の管理者はFirebirdにこの空きメモリをすべて消費させようとし、firebird.confのDefaultDBCachePageパラメータを非常に高い値に設定し、通常はスワップにつながります。
Windowsでの実際のメモリ使用量を確認するには、常にRAMMapツールを使用してください。
Windows Server(Firebirdサーバーとして使用する専用)の経験則は次のとおりです:Firebirdメモリ(ワーキングセット)は、総RAMの40%未満である必要があります。すべてのプロセスのワーキングセットの合計サイズが50%を超えると、Windowsによってスワップが開始される可能性があります。
注:「確保する」とは、ここでは「Firebirdでページバッファをあまり多く設定しない」という意味だけでなく、他のソフトウェアのメモリ使用量を制限することも重要です。たとえば、Firebirdと同じサーバーにMS ExchangeやMSSQLがある場合は、それらのメモリ使用量を制限してください。
詳細を知りたい場合は、Firebirdのメモリ管理に関するウェビナーを録画しました:
7. Linuxでファイルキャッシュ用にRAMの30%を確保する
LinuxはWindowsとは異なる方法でファイルキャッシュを処理し、一般的に、ファイルキャッシュに使用されるRAMの量は、Firebirdのパフォーマンスを著しく低下させることなく、Windowsよりも大幅に少なくできます。ただし、特にClassicおよびSuperClassicで、接続数が多いシステムの高性能を保証するには、ファイルキャッシュ用にRAMの30%を確保することをお勧めします。
8. Linuxでirqbalanceを使用する
irqbalanceは、コア数が多いサーバーでFirebirdのパフォーマンスとCPU負荷分散を向上させることがよくあります。
9. 仮想マシンの場合 - メモリオーバーコミットに注意
仮想マシンは、メモリオーバーコミットと呼ばれる機能(仮想化システムによって名前が異なる場合があります)により、ホストマシンに物理的に存在するよりも多くのメモリを持つように構成できます。これは、メモリ消費のピーク時(データベースサーバーがある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ファイルが数GBある可能性があり、それらをクリーンアップするとシステムドライブの空き容量が増えます。
12. 大きなFirebirdキャッシュでファイルキャッシュを有効にすることを忘れないでください
ご存知のように、Firebirdキャッシュ(「ページバッファ」とも呼ばれます)は、firebird.conf/databases.confのDefaultDBCachePagesパラメータ、またはデータベースのヘッダーで直接指定されます。
Firebird 3 SuperServerでは、このキャッシュのサイズを非常に高く設定できますが、もう1つのパラメータであるFileSystemCacheThresholdについて覚えておくことが重要です。
FileSystemCacheThresholdがDefaultDBCachePagesまたはページバッファより小さい場合、オペレーティングシステムのファイルキャッシュが使用されず、パフォーマンスの問題が発生する可能性があります。
99%の場合、ファイルキャッシュを有効にしておく方が良いです。
これを確実にするには、常に次のルールに従ってパラメータを設定してください:
- DefaultDBCachePages = X
- FileSystemCacheThreshold = X+N、N>1
ファイルキャッシュを無効にするとパフォーマンスが向上するまれなケースがあります - そのような例がある場合は、[email protected]までご連絡ください!
13. セキュリティデータベースを高速化する
Firebirdデータベースへの接続は毎回、セキュリティデータベース(Firebird 3の場合はsecurity3.fdb)への接続を確立し、いくつかの読み取りと書き込み(トランザクションページ、ヘッダーページ)を実行します。接続が頻繁な場合、セキュリティデータベースのパフォーマンスが問題になる可能性があります。
最低限でも、以下のことは実行できます:
- securityN.fdb のページバッファを増やす(経験的な最適値は 256 バッファ)
- security3.fdb を高速ドライブに移動する(Firebird 3 では標準機能ですが、2.5 では再インストールが必要になります)
その後、セキュリティデータベースに対して Forced Writes を OFF に設定できます - この場合、破損の可能性はわずかであり、問題にはなりません。
最も抜本的な方法は、セキュリティデータベースを読み取り専用にすることです - これにより、そこへのすべての書き込みが排除されます。
セキュリティデータベースのユーザーを頻繁に変更しないのであれば、これが最善の解決策です。
14. Firebird 3 で SuperClassic を試す
Firebird 3 では SuperServer アーキテクチャが究極のパフォーマンスソリューションとして大々的に宣伝されましたが、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)。
100Gb を超えるデータベースの場合、95% のケースで、利用可能な最大のページサイズを使用する方が良いです。その理由は以下の通りです:
- インデックスの深さを減らす。インデックスの深さは 3 以下にすることが推奨されます。深さ 4 および 5 のインデックスははるかに遅くなります。
- RAM の利用率を高める。Firebird キャッシュはページ単位で指定され、8K ページサイズで 1000 ページは実際のメモリ 8Mb になり、16K では 16Mb になります。
- システムページの数を減らす。これにより、大きなテーブルのレコードへのアクセスが高速化され(ポインタ-ポインタ-データページのジャンプが減る)、大きな SQL クエリの準備にも役立ちます。データベースのページサイズを増やすには、gbak ツールでデータベースをバックアップし、-page パラメータ(gbak -c -page 16384)を指定してリストアする必要があります。
注:多数の小さなブロブを含むデータベースの場合、ページサイズを増やすと断片化が減少するか増加するかのどちらかになり、パフォーマンスが向上するか低下するかを予測することは困難です。
16. no_reserve フラグを使用しない
no_reserve フラグは、UPDATE または DELETE 後に発生する可能性のあるレコードバージョン用にデータページに空き領域(30%)を予約しないように Firebird に指示します。このフラグにより、データをよりコンパクトに保存できます(データベースのサイズも小さくなります)が、UPDATE/DELETE の場合、すべての変更は新しいデータページに移動します。その結果、no_reserve フラグが設定されたデータベースでは UPDATE/DELETE 操作が遅くなります。
したがって、データベースが読み取り専用でない場合は、no_reserve フラグを削除することをお勧めします。
設定されているかどうかを確認するには、次の出力の Attributes 行を確認してください:
gstat -h database
無効にする方法:
gfix -use reserve database
このコマンドの後、新しいデータページは予約領域付きで作成されます。
ただし、完全な効果を得るには、gbak でデータベースをバックアップしてからリストアする必要があります。この場合、すべてのデータページに予約領域が設定されます。
注:no_reserve フラグを削除してバックアップ/リストアを行うと、データベースサイズは大きくなります。
17. Firebird ロックテーブルの初期サイズを大きく設定する
ロックテーブルは、Firebird のメカニズムであり、内部エンジンオブジェクトへのアクセスを同期するために使用されます。
Firebird ロックテーブルは自動的に拡張できますが、その拡張は遅い操作であり、マイクロフリーズを引き起こす可能性があります。ロックテーブルは初期サイズ(firebird.conf で設定)から拡張のみ可能です。
ロックテーブルの複数回の拡張を防ぐには、作業期間(日、週など)の終了時にロックテーブルのサイズを監視し、それを firebird.conf の初期サイズとして設定することをお勧めします。
LockMemSize=99999999
参考までに:高負荷システム(約 1000 ユーザー)での LockMemSize は通常 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 の条件は LEFT JOIN T2 の出力から NULL を除外するため、LEFT JOIN を INNER JOIN に変更してもクエリの結果には影響しません。
INNER JOIN は Firebird オプティマイザにより多くの自由度を与え、Firebird の最新バージョンでは LEFT よりもはるかに最適化されています。
特に以下の場合に有効です:
- WHERE 句に T1 の条件がない場合
- T2 が小さなテーブルの場合
20. 不要なレコード数のカウントを避ける
複雑なデータベースクエリやストアドプロシージャでのもう 1 つの一般的な間違いは、レコードの存在を確認するためだけに select count() を使用することです。
次のクエリは、condition1 に従ってすべてのレコードを読み取ります:
(select count(*)…. where condition11) >0
代わりに、次の構造を使用することをお勧めします:
Exists(select first 1 id where condition1)
condition1 が複数のレコードを返す場合、提案されたオプションははるかに高速です。すべてのレコードを読み取らず、最初にフェッチされたレコードの後に停止するためです。
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. 大規模なソートを含むクエリは常に閉じる
ソート(ORDER BY、GROUP BY、UNION、distinct)を含む SQL クエリが閉じられるまで、Firebird はソートされたレコードをメモリに保持します。ソート用に割り当てられるメモリサイズは、firebird.conf の TempCacheLimit パラメータで設定され、デフォルトでは 64Mb です。
TempCacheLimit を増やした場合でも、ソートされたレコードが多数ある長時間実行クエリは、最終的に割り当てられたすべての容量を消費し、その結果、ソートは一時ファイル(つまりディスク)に移動します。その結果、大幅な遅延が発生する可能性があります。
推奨事項は、そのようなクエリをすべてタイムリーに閉じることです。
ご質問は?
ご質問があれば、お気軽に [email protected] までご連絡ください!