PSQL Programmer's Guide (v11)

データベースの最適化 (トランザクショナル インターフェイス)

トランザクショナル データベース エンジンには、ディスク領域の節約とシステム パフォーマンスの向上を実現するいくつかの機能があります。これらの機能は以下のとおりです。

重複キー

キーを重複可能と定義すれば、トランザクショナル データベース エンジンは複数のレコードにそのキーの同じ値を持たせることができます。それ以外は、各レコードにそのキーの一意の値がなければなりません。セグメント化されたキーの 1 つのセグメントが重複可能であれば、すべてのセグメントが重複可能でなければなりません。

リンク重複キー

デフォルトでは、トランザクショナル データベース エンジンは v7.0 以降のファイルに重複キーをリンク重複キーとして格納します。重複キー値を持つ最初のレコードがファイルに挿入されると、トランザクショナル データベース エンジンはインデックス ページにキー値を格納します。トランザクショナル データベース エンジンはまた、このキー値で最初のレコードと最後のレコードを識別するために 2 つのポインターを初期化します。さらに、トランザクショナル データベース エンジンはレコードの終わりにあるポインターのペアをデータ ページに格納します。これらのポインターは、同じキー値で前のレコードと次のレコードを識別します。ファイルを作成する場合、将来リンク重複キーを作成する際に使用するポインターを予約することができます。

データ ファイルを作成した後に重複キーの追加を予測し、リンク重複方法を使用するためのキーが必要であれば、ファイル内にポインターのための領域をプリアロケートすることができます。

繰り返し重複キー

リンク重複キーを作成するための領域がない場合、つまり、重複ポインターがない場合、トランザクショナル データベース エンジンは繰り返し重複キーを作成します。トランザクショナル データベース エンジンは、データ ページ上とインデックス ページ上に繰り返し重複キーのすべてのキー値を格納します。つまり、キーの値はデータ ページ上のレコード内に存在し、インデックス ページ上のキー エントリで反復されます。


メモ

6.0 より前の Btrieve のユーザーの場合、リンク重複キー永続インデックスに対応し、繰り返し重複キー補足インデックスに対応します。


Create(14)オペレーションまたは Create Index(31)オペレーションのキーの仕様ブロックにキー フラグのビット 7(0x80)を設定することによって、キーを繰り返し重複キーとして定義できます。6.10 より前には、キーを繰り返し重複キーと定義できず、キー フラグのビット 7 はユーザーが定義できませんでした。6.0 以降では、リンク重複キーを作成するための領域がない場合、したがって、トランザクショナル データベース エンジンが繰り返し重複キーとしてキーを作成しなければならない場合、Stat オペレーション(15)がビット 7 を設定します。

5.x 形式を使用するファイルは、5.x では補足キー属性と呼ばれているこの同じキー フラグを使用して、キーが 5.x Create Supplemental Index オペレーション(31)で作成されたことを示します。


メモ

6.0 より前のファイルでは、補足インデックスだけが削除できます。永続インデックスは、その名前の示すとおり削除できません。6.0 以降のファイルでは、すべてのインデックスを削除できます。


リンクと繰り返し

各方法にはパフォーマンスの利点があります。

リンク重複キーと繰り返し重複キーの間には、パフォーマンスのトレードオフがあります。 一般に、キーの平均重複数が 2 つ以上であれば、リンク重複キーがディスク上で占有する領域は少なくなり、また、インデックス ページが少ないために一般には検索が高速になります。ただし、重複キーを持つレコードがほとんどファイルに格納されておらず、キー長が非常に短い場合は、その逆になります。それは、リンク重複ツリー内のエントリがポインターに 8 バイトを必要するのに対して、繰り返し重複キー エントリは 4 バイトを必要とするからです。

重複を持つキーがわずかしかない場合は、繰り返し重複キーを使用して各データ レコードに 8 バイトを追加保存するのが有利です。キー重複の平均数が 2 未満である場合は、いずれを選択してもパフォーマンス上の利点はそれほどありません。

いくつかの並行トランザクションが同時に同じファイル上でアクティブになると予想する場合、繰り返し重複キーの方が、これらのトランザクションが同じページにアクセスしない確率は高くなります。並行トランザクションでの書き込みに関連するすべてのページには、それらのページに対する暗黙ロックがあります。ある並行トランザクションで変更を行うためにページが必要であり、そのページが別の並行トランザクションに関与している場合、トランザクショナル データベース エンジンは別のトランザクションが終了するまで待ちます。このような暗黙の待ち時間が頻繁に発生する場合、アプリケーションのパフォーマンスは低下します。

いずれのキー格納方法も、年代順をトラッキングするための簡便法としては推奨しません。リンク重複キーの場合、トランザクショナル データベース エンジンはキーを作成した後に挿入されるレコードの年代順を維持しますが、キーのインデックスを作成し直した場合、年代順は失われます。繰り返し重複キーについては、キーを作成してから新しいレコードを挿入するまでの間にレコードの削除がなかった場合のみ、トランザクショナル データベース エンジンはレコードの年代順を維持します。年代順をトラッキングするには、キー上で AUTOINCREMENT データ型を使用します。

ページ プリアロケーション

プリアロケーションは、トランザクショナル データベース エンジンがディスク領域を必要とするときに、その領域が利用可能であることを保証します。トランザクショナル データベース エンジンでは、データ ファイルを作成するときにファイルに最大 65,535 ページをプリアロケートできます。表 26 は、65,535 全ページ分のディスク領域を割り当てるものと仮定して、トランザクショナル データベース エンジンが各ページ サイズのファイルに対して割り当てる最大バイト数を示したものです。

表 26 ページ サイズごとのディスク領域割り当て
ページ サイズ
割り当てられたディスク領域1
512
33,553,920
1,024
67,107,840
1,536
100,661,760
2,048
134,215,680
2,560
167,769,600
3,072
201,323,520
3,584
243,877,440
4,096
268,431,360
8,192
536,862,720
16,384
1,073,725,440
1値は、ページ サイズに 65,535 をかけたものです。

指定したページ数をプリアロケートするだけの十分な領域がディスクにない場合、トランザクショナル データベース エンジンはステータス コード 18(ディスクがいっぱい)を返し、ファイルを作成しません。

データ ファイルがディスク上の連続する領域を占有する場合、ファイル操作を高速化することができます。速度の向上は、非常に大きなファイルで最も顕著です。ファイルに連続するディスク領域をプリアロケートする場合、ファイルを作成するためのデバイスには必要なバイト数の連続する使用可能空き領域が必要です。トランザクショナル データベース エンジンは、ディスク上の領域が連続であるかどうかにかかわらず、指定するページ数をプリアロケートします。

ファイルに必要なデータ ページ数とインデックス ページ数を決定するには、この章の前半で説明した式を使用します。この部分の計算から出た剰余を次に大きい整数に切上げます。

ファイルのページをプリアロケートすると、そのファイルは実際にディスクのその領域を占有します。ほかのデータ ファイルは、そのファイルを削除または交換するまで、プリアロケートされたディスク領域を使用できません。

レコードを挿入すると、トランザクショナル データベース エンジンはデータとインデックスのプリアロケートされた領域を使用します。ファイルにプリアロケートされたすべての領域が使用されている場合、トランザクショナル データベース エンジンは新しいレコードが挿入されるたびにファイルを拡張します。

API の Stat オペレーション(15)を発行すると、トランザクショナル データベース エンジンはファイルの作成時に割り当てたページ数とトランザクショナル データベース エンジンが現在使用しているページ数の差を返します。この差が常に、プリアロケーションに指定したページ数より小さくなるのは、たとえレコードを何も挿入していなくても、ファイルの作成時に一定のページ数が使用されるとトランザクショナル データベース エンジンが見なすからです。

ファイル ページは一度使用されたら、たとえそのページに格納されているすべてのレコードを削除しても、ページは使用中のままになります。Stat オペレーションが返す未使用ページ数は増えません。レコードを削除すると、トランザクショナル データベース エンジンはファイル内の空き領域のリストを保守し、新しいレコードを挿入したときに使用可能な領域を再利用します。

たとえ Stat オペレーションが返す未使用ページ数が 0 であっても、ファイルにはまだ使用可能な空き領域があります。以下のいずれかが真であれば、未使用ページ数が 0 である可能性があります。

ブランク トランケーション

空白を切り捨てることにした場合、トランザクショナル データベース エンジンはファイルにレコードを書き込むときにレコードの可変長部分の末尾の空白を格納しません。ブランク トランケーションは、レコードの固定長部分に影響しません。トランザクショナル データベース エンジンは、データに埋め込まれている空白を削除しません。

切り捨てられた末尾の空白を含むレコードを読み取ると、トランザクショナル データベース エンジンはレコードを元の長さまで拡張します。トランザクショナル データベース エンジンがデータ バッファー長パラメーターで返す値には、拡張された空白が含まれています。ブランク トランケーションは、レコードの物理サイズに 2 バイトまたは 4 バイトのオーバーヘッドを追加し、固定長部分と一緒に格納します。ファイルが VAT を使用しない場合は 2、使用する場合は 4です。

レコード圧縮

ファイルを作成する場合、トランザクショナル データベース エンジンがファイルにデータ レコードを格納するときにデータ レコードを圧縮するかどうかを指定できます。レコード圧縮により、多数の繰り返し文字を含むレコードの格納に必要なスペースを大幅に削減できます。トランザクショナル データベース エンジンは、5 つ以上の同じ連続文字を 5 バイトに圧縮します。

以下の環境におけるレコード圧縮の使用方法について考えてみましょう。

圧縮されたファイルに対してレコード I/O を実行する場合、トランザクショナル データベース エンジンは圧縮バッファーを利用して、レコードの圧縮および拡張処理用のメモリ ブロックを提供します。レコードの圧縮や拡張を行うのに十分なメモリを確保するため、トランザクショナル データベース エンジンは、タスクが圧縮されたファイルに挿入する最長レコードの 2 倍の長さを格納できるだけのバッファー領域を必要とします。この要求は、トランザクショナル データベース エンジンがロードされた後にコンピューター内に残っている空きメモリ量に影響を与える可能性があります。たとえば、タスクが書き込むか取得する最長レコードが 64 KB の長さであれば、トランザクショナル データベース エンジンはそのレコードの圧縮および拡張に 128 KB のメモリを必要とします。


メモ

ファイルが VAT を使用している場合、トランザクショナル データベース エンジンが必要とするバッファー領域はファイルのページ サイズの 16 倍です。たとえば、4 KB のレコードでは、レコードの圧縮と拡張に 64 KB のメモリが必要になります。


圧縮されたレコードの最終の長さはそのレコードがファイルに書き込まれるまで決定できないので、トランザクショナル データベース エンジンは常に圧縮されたファイルを可変長レコード ファイルとして作成します。データ ページでは、トランザクショナル データベース エンジンは重複キー ポインターごとに、ファイルが VAT を使用しない場合は 7 バイト、使用する場合は 11 バイトを追加し、さらに、重複キー ポインターごとに 8  バイトを格納します。トランザクショナル データベース エンジンは次に、レコードを可変ページに格納します。レコードの圧縮されたイメージは可変長レコードとして格納されるので、タスクが頻繁な挿入、更新および削除を行う場合は、個々のレコードがいくつかのファイル ページにわたって断片化される場合があります。トランザクショナル データベース エンジンは 1 つのレコードを取得するために複数のファイル ページを読み取らなければならない場合があるので、この断片化によってアクセス時間が遅くなるおそれがあります。

レコード圧縮オプションは、各レコードが多数の繰り返し文字を取り込む可能性がある場合に最も有効です。たとえば、レコードにいくつかのフィールドが含まれており、レコードをファイルに挿入するときにそれらのフィールドはすべてタスクによって空白に初期化される可能性があります。圧縮は、これらのフィールドがほかの値を含むフィールドによって分離される場合でなく、レコード内で 1 つにグループ化される場合に有効です。

レコード圧縮を使用するには、圧縮フラグを設定してファイルを作成しておく必要があります。キーオンリー ファイルでは圧縮を行えません。

インデックス バランス

トランザクショナル データベース エンジンでは、インデックス バランスを使用することによってディスクをさらに節約できます。トランザクショナル データベース エンジンは、デフォルトではインデックス バランスを使用しないので、現在のインデックス ページがいっぱいになるたびに、トランザクショナル データベース エンジンは新しいインデックス ページを作成する必要があります。インデックス バランスが有効であれば、トランザクショナル データベース エンジンは現在のインデックス ページがいっぱいになるたびに、新しいインデックス ページを頻繁に作成しないようにすることができます。インデックス バランスを使用すると、トランザクショナル データベース エンジンは隣接するインデックス ページで使用可能な領域を探します。これらのページのうちの 1 つに領域がある場合、トランザクショナル データベース エンジンはいっぱいのインデックス ページから空き領域を持つページへキーを移動します。

インデックス バランス処理を実行すると、インデックス ページ数が少なくなるだけでなく、より密度の高いインデックスが作成され、ディスクの総利用率も上がり、大半の読み取り操作に対する応答が速くなります。ソート順でファイルにキーを追加する場合、インデックス バランスを使用していると、インデックス ページの利用率が 50% から 100% 近くまで増加します。ランダムにキーを追加する場合、最小のインデックス ページの利用率が 50% から 66% に増加します。

Insert オペレーションと Update オペレーションでは、バランス ロジックはファイル内のより多くのページを調べるようにトランザクショナル データベース エンジンに要求し、より多くのディスク I/O を要求する可能性があります。余分なディスク I/O はファイル更新速度を下げます。インデックス バランスの正確な影響は状況によって異なりますが、インデックス バランスを使用した場合、書き込み操作のパフォーマンスは概して約 5~10% 低下します。

トランザクショナル データベース エンジンは 2 つのレベル、つまり、エンジン レベルとファイル レベルのインデックス バランスを提供するので、トランザクショナル データベース エンジン環境を微調整することができます。セットアップ中にインデックス バランス設定オプションを指定すると、トランザクショナル データベース エンジンはすべてのファイルにインデックス バランスを適用します。インデックス バランス設定オプションの指定方法については、『Pervasive PSQL User's Guide』を参照してください。

特定のファイルだけにインデックス バランスを行うように指定することもできます。そうするには、ファイル作成時にファイル フラグのビット 5(0x20)を設定します。トランザクショナル データベース エンジンを起動したときにインデックス バランス設定オプションがオフであれば、トランザクショナル データベース エンジンはビット 5 のファイル フラグを設定したファイル上のインデックスだけにインデックス バランスを適用します。

トランザクショナル データベース エンジンを起動したときにインデックス バランス設定オプションがオンであった場合、トランザクショナル データベース エンジンはすべてのファイルのファイル フラグ内のビット 5 を無視します。この場合、トランザクショナル データベース エンジンはすべてのファイルにインデックス バランスを適用します。

ファイルは、インデックス バランスが有効であるかどうかに関係なく互換性があります。また、インデックス バランスが使用されたインデックス ページを含むファイルにアクセスするために、インデックス バランスを指定する必要はありません。トランザクショナル データベース エンジンのインデックス バランス オプションをオンにした場合、既存のファイル内のインデックス ページはいっぱいになるまで影響を受けません。トランザクショナル データベース エンジンは、このオプションを有効にした結果として既存のファイルに対し再度インデックス バランスを行いません。同様に、インデックス バランス オプションをオフにしても、既存のインデックスは影響を受けません。このオプションのオン、オフにより、トランザクショナル データベース エンジンがいっぱいになったインデックス ページを処理する方法が決まります。

可変長部割り当てテーブル

可変長部割り当てテーブルを使用すると、トランザクショナル データベース エンジンは非常に大きなレコード内に大きなオフセットで存在するデータに対してさらに高速にアクセスでき、データ圧縮を使用するファイル内のレコードを処理するときにトランザクショナル データベース エンジンが要求するバッファー サイズが大幅に削減されます。レコードの VAT を使用すると、トランザクショナル データベース エンジンはレコードの可変長部分をさらに小さな部分に分割し、次にこれらの部分をいくつもの可変長部に格納します。トランザクショナル データベース エンジンは、同量のレコード データを、レコードの可変長部に格納します。ただし、最後の可変長部は異なることがあります。トランザクショナル データベース エンジンは、ファイルのページ サイズに 8 をかけて、各可変長部に格納する量を計算します。最後の可変長部には、トランザクショナル データベース エンジンがほかの可変長部にデータを分割した後に残るデータが含まれています。


メモ

可変長部の長さを算出する式(ページ サイズの 8 倍)は、トランザクショナル データベース エンジンの将来のバージョンでは変更される可能性があります。


VAT を使用し、4,096 バイトのページ サイズを持つファイルでは、第 1 の可変長部にレコードの可変部分のオフセット 0~32,767 のバイトが格納され、第 2 の可変長部にオフセット 32,768~65,535 が格納され、以降同様に格納されます。トランザクショナル データベース エンジンが VAT を使用してレコード内の大きなオフセットまでのシークを加速できるのは、VAT を使用すると、レコードの下位オフセットのバイトを含んでいる可変長部をスキップできるからです。

アプリケーションでは、ファイルの作成時に VAT を使用するようにするかどうかを指定します。アプリケーションが非常に大きな、物理ページ サイズの 8 倍を越えるレコードに対して Chunk オペレーションを使用し、順次でないランダムな方法でチャンクにアクセスする場合は、VAT によってアプリケーションのパフォーマンスが向上する可能性があります。アプリケーションがレコード全体に対する操作を行う場合は、VAT によってパフォーマンスは向上しません。この場合、トランザクショナル データベース エンジンはレコードを順次に読み書きし、トランザクショナル データベース エンジンはレコード内のどのバイトもスキップしないからです。

アプリケーションが Chunk オペレーションを使用するがレコードに順次アクセスする場合(たとえば、レコードの最初の 32 KB を読み、次の 32 KB を読み、という具合にレコードの最後まで読む)、VAT はパフォーマンスを向上させません。これは、トランザクショナル データベース エンジンがオペレーション間でレコード内の位置を保存することによって Chunk オペレーションが先頭からシークする必要性をなくしているためです。

VAT には別の利点もあります。トランザクショナル データベース エンジンが圧縮されたレコードを読み書きする場合、使用するバッファー サイズは、レコードの未圧縮サイズの最大 2 倍必要です。ファイルに VAT がある場合、そのバッファーは 2 つの可変長部と同じ大きさ、つまり、物理ページ サイズの 16 倍あれば済みます。

キーオンリー ファイル

キーオンリー ファイルでは、レコード全体がキーと共に格納されるため、データ ページは不要です。キーオンリー ファイルは、レコードに単一のキーが含まれており、かつそのキーがレコードの大部分を占有している場合に有効です。キーオンリー ファイルのもう 1 つの一般的な用途は、標準ファイルの外部インデックスとしての使用です。

キーオンリー ファイルには以下の制限が適用されます。

キーオンリー ファイルには、後ろに多数の PAT ページとインデックス ページが付いたファイル コントロール レコード ページしか含まれていません。キーオンリー ファイルに ACS がある場合、ACS ページもある可能性があります。ODBC を使用してファイルに参照整合性制約を定義した場合、ファイルには 1 つまたは複数の可変ページも含まれます。


ファイル サイズの予測 (トランザクショナル インターフェイス)

セキュリティの設定 (トランザクショナル インターフェイス)