Blackfish SQL アプリケーションの最適化
このセクションでは,Blackfish SQL アプリケーションのパフォーマンス,信頼性,およびサイズの改善に役立つ方法を示します。特に断らない限り,DataStoreConnection とは,Blackfish SQL データベースファイルへの接続を開くために使用される DataStoreConnection オブジェクトまたは DataStore オブジェクトを指します。
データベースの高速読み込み
次に,データベースを読み込むときにアプリケーションのパフォーマンスの向上に役立ついくつかのヒントを示します。
- 可能な限り,準備された文またはコマンドを使用します。パラメータ数が,ある挿入から次の挿入までに変化する場合は,新しいパラメータを設定する前にそれらのパラメータをクリアします。
- 主キー,外部キー,または二次インデックスを使用せずにテーブルを作成します。テーブルを読み込んでから,必要なすべての主キー,外部キー,または二次インデックスを作成します。
Java 固有のデータベース読み込みの最適化
DataExpress TextDataFile クラスを使ってテキストファイルをインポートします。このメソッドは高速のパーサーを持つため,データを高速に読み込むことができます。StorageDataSet ストアを DataStoreConnection に設定し,StoreName プロパティを Blackfish SQL データベースのテーブル名に設定する必要があります。新しいデータベースを読み込む場合は,次の手順を実行します。
- 最初に,データベースを非トランザクション対応として作成します。
- データベースが非トランザクション対応である間に,DataExpress StorageDataSet.addRow または TextDataFile コンポーネントを使用して,データベースを読み込みます。
- データベースが読み込まれたら,DataStore.TxManager プロパティを使ってデータベースをトランザクション対応にします。
この方法を使用すると,データベースの読み込みが 2 ~ 3 倍高速になります。
一般的な推奨事項
このセクションでは,Blackfish SQL アプリケーションのパフォーマンスを改善するための一般的なガイドラインを提供します。
適切なデータベースのシャットダウン
データベースが正しくシャットダウンされなかった場合,次回,そのデータベースを開く際に遅延が発生します。これは,Blackfish SQL が他のプロセスでデータベースが開かれていないことを確認するために 8 ~ 10 秒かかるためです。データベースを正しくシャットダウンするには,不要になった接続をすべて閉じてください。すべての接続が閉じられていることの確認が困難な場合は,管理者権限を使用した接続から組み込みのストアドプロシージャ DB_ADMIN.CLOSE_OTHER_CONNECTIONS を呼び出すことで,他のすべての接続を確実に閉じることができます。
接続を閉じることのもう 1 つの利点として,接続をすべて閉じると,Blackfish SQL キャッシュに割り当てられていたメモリーが解放されます。
現在,非トランザクション対応のデータベースには,データベースの読み取り専用プロパティが true に設定されている場合にだけ SQL からアクセスできます。ただし,DataExpress JavaBeans は,非トランザクション対応のデータベースに対して書き込み操作を実行できます。
非トランザクション対応の Blackfish SQL データベースを閉じると,すべての変更内容が確実にディスクに保存されます。すべての開かれた DataStoreConnection インスタンスに対して 1 つのデーモンスレッドがあり,これが,変更されたキャッシュデータを常時保存しています。デフォルトでは,変更されたデータは 500 ミリ秒ごとに保存されます。データベースを閉じずに Java 仮想マシンを直接終了すると,このデーモンスレッドが最後の変更セットを保存する機会を失う可能性があります。非トランザクション対応の Blackfish SQL が損傷を受ける可能性は,わずかですがあります。
トランザクション対応の Blackfish SQL データベースにはデータ損失がないことが保証されます。ただし,コミットされていない変更があれば,トランザクションマネージャによってロールバックされます。
Java 固有のデータベースのシャットダウン
アプリケーションで DataExpress JavaBeans コンポーネントを使用している場合は,それらのコンポーネントを使用し終わったら,store プロパティが DataStoreConnection に設定されている StorageDataSet をすべて閉じてください。これにより,StorageDataSet に関連付けられている Blackfish SQL のリソースが解放され,StorageDataSet がガベージコレクションの対象となります。
DataStore.shutdown() メソッドを使用して,アプリケーションを終了する前に,すべてのデータベース接続を確実に閉じることができます。
Blackfish SQL ディスクキャッシュの最適化
Blackfish SQL データベースのデフォルトの最大キャッシュサイズは 512 キャッシュブロックです。デフォルトブロックサイズは 4096 バイトです。したがって,キャッシュメモリーは,約 512*4096(2MB)で最大容量に達します。このメモリーは必要に応じて割り当てられます。すべてのブロックが使用されるようなまれに起きる状況においては,キャッシュが 512 キャッシュブロックより大きくなることがあります。最小キャッシュサイズは,DataStore.MinCacheSize プロパティを使って指定できます。
メモ:不用意にデータベースのキャッシュサイズを変更しないでください。最初に,変更によってアプリケーションのパフォーマンスが向上することを必ず確認してください。
Blackfish SQL キャッシュサイズを変更するときは,次の点に注意してください。
- 最新の OS キャッシュは一般に高パフォーマンスです。多くの場合,Blackfish SQL キャッシュサイズを増やしても,大幅なパフォーマンスの向上につながらず,単にメモリーの余分な浪費となるだけです。
- 同じプロセスで開いているすべての Blackfish SQL データベースに対して,Blackfish SQL ディスクキャッシュは 1 つしかありません。すべての Blackfish SQL データベースをシャットダウンすると,このグローバルディスクキャッシュのメモリーが解放されます。
- 小容量のメモリーが搭載されたハンドヘルドデバイスでは,DataStore.MinCacheSize プロパティは 96 などの小さい数値に設定します。
ファイルアクセスの最適化
Blackfish SQL データベースでは,読み取り/書き込み操作のほとんどを次の 4 種類のファイルに対して行います。
- DataStore.FileName プロパティで指定される Blackfish SQL データベースファイル自身(ファイル名拡張子は .jds)。
- TxManager.ALogDir プロパティで指定される Blackfish SQL トランザクション対応ログファイル(ファイル名拡張子は LOGAnnnnnnnnnn。n には数字が入ります)。
- DataStore.TempDirName プロパティで指定される大規模なソート操作に使用する一時ファイル。
- DataStore.TempDirName プロパティで指定される SQL クエリーの結果に使用する一時 .jds ファイル。
上述のファイルを異なるディスクドライブに置くように Blackfish SQL に指示することにより,パフォーマンスの向上が期待できます。
ファイルストレージ
次に,アプリケーションのパフォーマンスを改善できる可能性があるファイルストレージ処理のいくつかのガイドラインを示します。
- ログファイルを別のディスクドライブに置くことが特に重要です。ログファイルは,通常,順次に追加され,コミット操作を完了するには,その内容をディスクに強制的に保存する必要があります。このため,書き込み操作をすばやく完了できるディスクドライブがあると有利です。
- Win32 プラットフォームの場合は,Blackfish SQL ログファイルを別のディレクトリに配置することでパフォーマンスが向上する可能性があります。ログファイルディレクトリにログファイル以外の多くのファイルを保存すると,コミット操作のパフォーマンスが低下する可能性があります。このパフォーマンス上のヒントは,Windows NT/2000/XP 以外のプラットフォームにも適用されます。
- ディスクドライブのファイルシステムは必ず定期的に最適化してください。Blackfish SQL はログファイルに対して大量のシーケンシャルな読み取り/書き込み操作を行うため,ログファイルを保存するディスクドライブの最適化は特に重要です。
- Win32 プラットフォームの場合,ログファイルが書き込まれるディスクドライブに対しては,FAT32 ファイルシステムと大きなクラスタサイズ(64KB など)を使用してください。
Java の非トランザクション対応データベースディスクキャッシュ書き込みオプション
メモ: このセクションは,DataExpress JavaBeans コンポーネントを使用する Blackfish SQL for Java だけに適用されます。
キャッシュブロックのディスクへの書き込み回数を制御するには,DataStore コンポーネントの saveMode プロパティを使用します。このプロパティは,非トランザクション対応の Blackfish SQL データベースだけに適用されます。このメソッドには,次の値を指定できます。
|
0 |
デーモンスレッドがすべてのキャッシュ書き込みを処理します。この設定によってパフォーマンスは最高になりますが,エラーの危険性も最も高くなります。 |
|
1 |
ブロックの追加や削除の後,すぐに保存を行います。この他の変更内容は,すべてデーモンスレッドが処理します。これがデフォルトのモードです。パフォーマンスは saveMode(0) の場合とほとんど変わりません。 |
|
2 |
すべての変更をすぐに保存します。DataStore コンポーネントを使用するアプリケーションをデバッグする場合は,必ずこの設定を使用してください。 |
DataStore の他のプロパティとは異なり,saveMode は,接続の開始後でも変更できます。たとえば,DataStoreConnection を使用している場合は,その dataStore プロパティを介してその値にアクセスできます。
DataStoreConnection store = new DataStoreConnection(); ... store.getDataStore().setSaveMode(2);
これにより,その Blackfish SQL データベースファイルにアクセスするすべての DataStoreConnection オブジェクトの動作が変更されることに注意してください。
メモリーの調整
複数の方法でメモリーの使用量を調節できます。メモリーを要求しすぎると,メモリーが足りない場合と変わらなくなる可能性があることに注意してください。
- ConnectionProperties.MinCacheBlocks プロパティの値を増やしてみます。このプロパティは,キャッシュされるブロックの最小数を制御します。
- ConnectionProperties.MaxSortBuffer プロパティは,インメモリーソートに使用するバッファの最大サイズを制御します。このバッファサイズを超える場合は,より低速のディスクベースのソートが使用されます。
Java 固有のメモリーの調整
Java のヒープは,初期のサイズを超えないように,より小さな空きのヒープの量に対して頻繁にガベージコレクションを行う傾向があります。より大きな初期ヒープサイズを指定するには,JVM -Xms オプションを使用します。通常は,JVM の -Xms と -Xmx の設定を同じにすると最適です。
その他のパフォーマンス上のヒント
次に,パフォーマンスの向上に役立つヒントを示します。
- クエリーエンジンに使用される ConnectionProperties.TempDirName プロパティを他の(より高速な)ディスクドライブのディレクトリに設定するとよい場合があります。
- トランザクションマネージャのチェックポイントの頻度を変更してみます。値を大きくするほどパフォーマンスは向上しますが,クラッシュ回復が遅くなる場合があります。これは,組み込みのストアドプロシージャ DB_ADMIN.ALTER_DATABASE を使用して,SQL から更新できます。Blackfish SQL for Java では,JdsExplorer を使用し,TxManager > Modify を選択することで,このプロパティを設定できます。
トランザクション対応アプリケーションの最適化
トランザクション対応の Blackfish SQL データベースを使用すると,信頼性と柔軟性は高まりますが,パフォーマンスは低下します。これを改善するには,いくつかの方法があります。次のセクションでは改善方法について説明します。
読み取り専用トランザクションの使い方
書き込みがなく,読み取りだけを行うトランザクションでは,読み取り専用トランザクションを使用すると,パフォーマンスを大幅に向上させることができます。接続の readOnly プロパティは,トランザクションを読み取り専用にするかどうかを制御します。Blackfish SQL for Java の DataStoreConnection JavaBeans には,読み取り専用トランザクションを有効にする readOnlyTx プロパティがあります。
読み取り専用のトランザクションは,Blackfish SQL データベースのスナップショットのように機能します。このスナップショットには,読み取り専用トランザクションが起動した時点でコミットされているトランザクションからのデータだけが表示されます。スナップショットは,DataStoreConnection が開かれたときに作成され,その commit メソッドが呼び出されるたびに更新されます。
読み取り専用トランザクションのもう 1 つの利点は,書き込みまたは他の読み取りにブロックされないことです。通常,読み取り/書き込みにはロックが必要です。しかし,読み取り専用トランザクションではスナップショットを使用するため,ロックは必要ありません。
readOnlyTxDelay プロパティの値を設定することで,アプリケーションをさらに最適化できます。readOnlyTxDelay プロパティは,接続が共有できる既存のスナップショットの最大経過時間をミリ秒単位で設定します。このプロパティの値が 0 でない場合は,最新のものから順に既存のスナップショットが検索されます。経過時間が readOnlyTxDelay より小さいスナップショットがある場合は,それが使用され,新しいスナップショットは取得されません。デフォルトでは,このプロパティは 5000 ミリ秒に設定されています。
ソフトコミットモードの使い方
SoftCommit プロパティでソフトコミットモードを有効にした場合,トランザクションマネージャは,コミットされたトランザクションのログ記録を引き続き書き込みますが,コミット操作の同期書き込みメカニズムは使用しません。ソフトコミットが有効な場合,オペレーティングシステムキャッシュは,コミットされたトランザクションによるファイルの書き込みをバッファできます。通常,オペレーティングシステムは,ダーティキャッシュブロックを数秒以内にディスクに書き込むことになります。ソフトコミットによってパフォーマンスは向上しますが,最も新しくコミットされたトランザクションの耐久性は保証されません。組み込みのストアドプロシージャ DB_ADMIN.ALTER_DATABASE を呼び出すことで,SoftCommit プロパティを設定できます。
トランザクションログファイルのステータスログの無効化
ステータスメッセージのログをオフにして,パフォーマンスを向上させることもできます。それには,RecordStatus プロパティを false に設定します。組み込みのストアドプロシージャ DB_ADMIN.ALTER_DATABASE を呼び出すことで,RecordStatus プロパティを設定できます。
Blackfish SQL 並行処理制御のパフォーマンス
次に,Blackfish SQL 並行処理制御操作のパフォーマンスを最適化するためのガイドラインを示します。
- アプリケーションが正しく機能する最も低いアイソレーションレベルを選択します。低いアイソレーションレベルはロックが少なく,弱いロックで済みます。
- 複数の文を単一のトランザクションにまとめます。デフォルトが自動コミットモードの接続は,各文の実行後にコミットされます。
- トランザクションはできるだけ早くコミットします。ほとんどのロックは,トランザクションがコミットされるか,ロールバックされるまで解放されません。
- 可能な場合は,文またはコマンドオブジェクトを再利用します。さらに可能であれば,準備された文またはコマンドを使用します。
- 不要になった文またはコマンド,結果セット,読み取りオブジェクト,接続オブジェクトをすべて閉じます。単一方向の結果セットまたは読み取りオブジェクトは,最後の行が読み取られると自動的に閉じられます。
- 長いレポートやオンラインバックアップ操作には,読み取り専用トランザクションを使用します。オンラインバックアップには,DB_ADMIN.COPYDATABASE メソッドを使用します。読み取り専用トランザクションを使用すると,アクセスしたテーブルに対して,トランザクションとして一貫性のある(シリアル化可能な)読み取り専用の表示を行うことができます。ロックを取得しないため,ロックのタイムアウトやデッドロックがありません。「読み取り専用トランザクションの使用」を参照してください。
- 読み取り専用ビューの維持には,ある程度のオーバーヘッドがあります。したがって,複数のトランザクションが同じ読み取り専用ビューを共有することもあります。ConnectionProperties.ReadOnlyTxDelay プロパティは,トランザクションが開始されたときに,読み取り専用ビューがどの程度古くてもよいかを指定します。読み取り専用接続のトランザクションをコミットすると,データベースのビューが更新されます。読み取り専用トランザクションは,トランザクション用のログファイルを使ってビューを維持します。このため,読み取り専用接続は,不要になったらすぐに閉じる必要があります。
マルチスレッドの使い方
それぞれのスレッドは,Blackfish SQL の提供する「グループコミット」サポートを経由してコミット操作におけるオーバーヘッドを共有できるため,操作の実行に使用されるスレッドが増えれば増えるほど,書き込みトランザクションの処理能力は向上します。
Blackfish SQL for Java アプリケーションの配布リソースの簡潔化
Blackfish SQL アプリケーションを配布する場合は,使用しない一部のクラスファイルや画像ファイルを取り除くことができます。
- JDBC ドライバを使用しないで Blackfish SQL を使用する場合は,次のクラスを削除できます。
- com.borland.datastore.Sql*.class
- com.borland.datastore.jdbc.*
- com.borland.datastore.q2.*
- DataExpress を使用し,StorageDataSet.store プロパティが必ず DataStore や DataStoreConnection のインスタンスに設定される場合は,次のクラスを削除できます。
- com.borland.dx.memorystore.*
- StorageDataSet を使用しても,QueryDataSet,QueryProvider,StoredProcedureDataSet,または StoredProcedureProvider を使用しない場合は,次のクラスを削除できます。
- com.borland.dx.sql.*
- DataExpress が JBCL や dbSwing のライブラリのビジュアルコンポーネントを使用しない場合は,次のクラスを削除できます。
- com.borland.dx.text.*
- com.borland.dx.dataset.TextDataFile を使用しない場合は,次のクラスを削除できます。
- com.borland.jb.io.*
- com.borland.dx.dataset.TextDataFile.class
- com.borland.dx.dataset.SchemaFile.class
AutoIncrement 列
int 型と long 型の列は,AutoIncrement 値を持つように指定できます。
すべての AutoIncrement 列値に次の属性が適用されます。
- 常に一意な値
- null 値の使用不可
- 削除された行の値は再利用不可
これらの属性があるため,AutoIncrement 列は,単一列の integer/long 主キーに適しています。
AutoIncrement 列は行の内部識別子なので,Blackfish SQL テーブル内の特定の行に最速のランダムアクセスパスを提供します。
1 つのテーブルにつき AutoIncrement 列は 1 つしか使用できません。 主キーのかわりとして AutoIncrement 列を使用すると,テーブル内の 1 つの整数列と 1 つの二次インデックスの領域を節約できます。Blackfish SQL クエリーオプティマイザは,WHERE 句で AutoIncrement 列を参照するクエリーを最適化します。SQL で AutoIncrement 列を使用する方法については,「SQL リファレンス」の「SQL による自動インクリメント列の使用」を参照してください。
Blackfish SQL for Java の DataExpress JavaBeans を使用する AutoIncrement 列
DataExpress で AutoIncrement 列のあるテーブルを作成するには,テーブルを開く前に Column.AutoIncrement プロパティを true に設定します。既存のテーブルを変更する場合は,StorageDataSet.restructure() メソッドを呼び出す必要があります。
Blackfish SQL 付随コンポーネント
dbSwing コンポーネントライブラリにある次の 2 つのコンポーネント(コンポーネントパレットの[More dbSwing]ページ)を使用すると,安定した Blackfish SQL アプリケーションを容易に作成できます。
- DBDisposeMonitor は,コンテナが閉じらるとデータベース対応コンポーネントのリソースを自動的に破棄します。このコンポーネントには closeDataStores プロパティがあります。これが true(デフォルト)の場合は,破棄するコンポーネントに結び付けられているすべての Blackfish SQL データベースが自動的に閉じられます。 たとえば,JFrame の中に,Blackfish SQL データベースに結び付けられた dbSwing コンポーネントがあり,そこに DBDisposeMonitor を追加したとします。JFrame を閉じると,DBDisposeMonitor は Blackfish SQL データベースを自動的に閉じます。このコンポーネントは,簡単なアプリケーションを作成して Blackfish SQL の動作を確認する場合に特に便利です。
- DBExceptionHandler には[終了]ボタンがあります。プロパティの設定によって非表示にもできますが,デフォルトでは表示されます。このボタンをクリックすると,開いているすべての Blackfish SQL データベースファイルが自動的に閉じられます。DBExceptionHandler は,例外の発生時に dbSwing コンポーネントによって表示されるデフォルトのダイアログボックスです。
Blackfish SQL for Java の DataExpress JavaBeans コンポーネント用のデータモジュールの使用
Blackfish SQL テーブルを StorageDataSet とともに使用する場合は,すべてのデータセットをデータモジュール内にグループ化する必要があります。businessModule.getCustomer などの DataModule のアクセッサメソッドを使用して,これらの StorageDataSet への参照を作成します。これは,StorageDataSet を通して得られる多くの機能がプロパティやイベントの設定を使用しているためです。
重要な構造化された StorageDataSet プロパティのほとんどは Blackfish SQL テーブル自体に永続化されますが,イベントリスナのインターフェースを実装するクラスはそうではありません。これらのクラスは,すべてのイベントリスナの設定,constraints,計算フィールド,およびイベントに実装されたフィルタを使って StorageDataSet をインスタンス化することで,実行時にも設計時にも正しく維持されているかどうかを確認します。