PSQL Programmer's Guide (v11)

データ ファイルの作成 (トランザクショナル インターフェイス)

トランザクショナル インターフェイスは、データベース アプリケーションを最適化する際の大きな柔軟性を開発者に与えてくれます。そのような柔軟性を提供するため、トランザクショナル インターフェイスは、トランザクショナル データベース エンジンの内部処理の多くを公開しています。トランザクショナル インターフェイスを初めて使用する場合、Create(14)オペレーションは非常に複雑に見えるかも知れませんが、作業の開始にあたってはこのオペレーションのすべての機能を必要とするわけではありません。ここでは、簡単なトランザクション ベースのデータ ファイルの作成を段階的に行うことで、基本的な条件に焦点を当てます。ここでは、必要に応じて簡素化を図るために、C インターフェイスの用語を使用します。


メモ

同じディレクトリに、ファイル名が同一で拡張子のみが異なるようなファイルを置かないでください。たとえば、同じディレクトリ内のデータ ファイルの 1 つに Invoice.btr、もう 1 つに Invoice.mkd という名前を付けてはいけません。このような制限が設けられているのは、データベース エンジンがさまざまな機能でファイル名のみを使用し、ファイルの拡張子を無視するためです。ファイルの識別にはファイル名のみが使用されるため、ファイルの拡張子だけが異なるファイルは、データベース エンジンでは同一のものであると認識されます。


データ レイアウト

ここでは、社員レコードを格納するデータ ファイルの例を使用します。アプリケーションは、一意の社員 IDまたは社員のラスト ネームを指定して社員情報を取得します。複数の社員が同じラスト ネームを持っている可能性があるので、データベースではラスト ネームの重複値を許します。これらの基準に基づくと、ファイルのデータ レイアウトは以下のようになります。

レコード内の情報
データ型
キーまたはインデックスの特性
ラスト ネーム
25 文字の文字列
重複可能
ファースト ネーム
25 文字の文字列
なし
ミドル イニシャル
1 文字の文字列
なし
社員 ID
4 バイト整数
重複不可
電話番号
13 文字の文字列
なし
月給
4 バイト浮動小数
なし

基本的なデータ レイアウトを設定したので、トランザクショナル インターフェイスの用語と条件の適用を開始できます。この場合、実際にファイルを作成する前にキー構造とファイル構造に関する情報を決定します。これらの詳細情報を事前に処理しておかなければならないのは、Create(14)オペレーションがファイル情報、インデックス情報、キー情報をすべて一度に作成するからです。以降では、これらの詳細情報を処理する際に考慮しなければならない問題について説明します。

キー属性

まず、キーの特別な機能を決定します。以下の表に示すように、トランザクショナル データベース エンジンにはさまざまなキー属性があり、必要に応じ割り当てることができます。

表 13 キー属性
定数
説明
EXTTYPE_KEY
拡張データ型。文字列または符号なしバイナリ以外のトランザクショナル インターフェイス データ型を格納します。標準バイナリ データ型よりもこの属性を使用してください。このキー属性には、標準バイナリおよび文字列データ型のほかに多数の属性を収容できます。
BIN
標準バイナリ データ型。今日までの経緯によりサポートされます。符号なし 2 進数を格納します。デフォルトのデータ型は文字列です。
DUP
リンク重複。ポインターでインデックス ページからデータ ページへリンクされる重複値を許します。詳細については、重複キーを参照してください。
REPEAT_DUPS_KEY
繰り返し重複。インデックス ページとデータ ページの両方に格納される重複値を許します。詳細については、重複キーを参照してください。
MOD
変更可能。レコードの挿入後にキー値の変更を行えます。
SEG
セグメント化。このキーが、現在のキー セグメントの後にセグメントを持つことを指定します。
NUL
ヌル キー(すべてのセグメント)。指定されたヌル値がキーのすべてのセグメントに含まれている場合は、インデックスからすべてのレコードを除外します(ファイルを作成するときにヌル値を指定します)。
MANUAL_KEY
ヌル キー(任意のセグメント)。指定されたヌル値がキーの任意のセグメントに含まれている場合は、インデックスからすべてのレコードを除外します(ファイルを作成するときにヌル値を指定します)。
DESC_KEY
降順のソート順序。キー値を降順(最大から最小へ)に並べます。デフォルトは昇順(最小から最大へ)です。
NOCASE_KEY
大文字と小文字の区別。大文字と小文字を区別せずに文字列値をソートします。キーにオルタネート コレーティング シーケンス(ACS)がある場合は使用しないでください。ヌル インジケーター セグメントの場合、ゼロではないヌル値を明確に区別するために重ねて定義されます。
ALT
オルタネート コレーティング シーケンス。ACS を使用して標準の ASCII 照合順序から異なる方法で文字列キーをソートします。各種キーは異なる ACS を使用できます。デフォルト ACS(ファイルで定義された最初の ACS)、ファイル内で定義された番号付き ACS、または、COLLATE.CFG システム ファイルで定義された名前付き ACS を指定できます。
NUMBERED_ACS
NAMED_ACS
簡素化を図るために、これらの定数は btrconst.h で定義され、C インターフェイスに合致しています。インターフェイスの中には、ほかの名前を使用したり、定数をまったく使用しないものがあります。ビット マスク、キー属性の 16 進値および 10 進値については、『Btrieve API Guide』を参照してください。

定義するキーごとに、これらのキー属性を指定します。各キーは独自のキー仕様を持ちます。キーに複数のセグメントがある場合は、セグメントごとに仕様を提供する必要があります。これらの属性のいくつかは、同じキー内の異なるセグメントに対して異なる値を持つことができます。

前の例で、キーはラスト ネームおよび社員 ID です。どちらのキーも拡張型を使用します。つまり、ラスト ネームは文字列、社員 ID は整数です。両方とも変更可能ですが、ラスト ネームだけは重複可能です。また、ラスト ネームは大文字と小文字を区別します。

キーに割り当てるデータ型に関して、トランザクショナル インターフェイスは、入力レコードがそのキーに対し定義されたデータ型に従っているかどうかを確認しません。たとえば、ファイルで TIMESTAMP キーを定義したとします。そこに文字列を格納したり、または日付キーを定義し 2 月 30 日の値を格納したりすることができます。お使いのトランザクショナル インターフェイス アプリケーションは問題なく機能しますが、同じデータにアクセスしようとする ODBC アプリケーションではうまくいかない可能性があります。それは、バイト 形式が異なり、タイムスタンプ値を生成するためのアルゴリズムが異なるためです。データ型の説明については、『SQL Engine Reference』を参照してください。

ファイル属性

次に、ファイルの特別な機能を決定します。

以下の表に示すように、トランザクショナル データベース エンジンではさまざまな種類のファイル属性が指定できます。

表 14 ファイル属性
定数
説明
VAR_RECS
可変長レコード。可変長レコードを含むファイルで使用します。
BLANK_TRUNC
ブランク トランケーション。レコードの可変長部分の末尾の空白を削除することによって、ディスク領域を節減します。可変長のレコードを許し、かつデータ圧縮機能を使用しないファイルにのみ適用できます。詳細については、ブランク トランケーションを参照してください。
PRE_ALLOC
ページ プリアロケーション。ファイルの作成時にファイルで使用される連続ディスク領域を予約します。ファイルがディスク上の連続する領域を占有する場合、ファイル操作を高速化することができます。速度の向上は、非常に大きなファイルで最も顕著です。詳細については、ページ プリアロケーションを参照してください。
DATA_COMP
データ圧縮。レコードを挿入または更新する前に圧縮し、レコードの取得時に解凍します。詳細については、レコード圧縮を参照してください。
KEY_ONLY
キーオンリー ファイル。キーを 1 つだけ含み、レコード全体がそのキーと共に格納されるため、データ ページは不要です。キーオンリー ファイルは、レコードに単一のキーが含まれており、かつそのキーが各レコードの大部分を占有している場合に有効です。詳細については、キーオンリー ファイルを参照してください。
BALANCED_KEYS
インデックス バランス。いっぱいになったインデックス ページから領域が空いているインデックス ページへ値を振り分けます。インデックス バランスは読み取り操作でのパフォーマンスを高めますが、書き込み操作では余計な時間がかかる場合があります。詳細については、インデックス バランスを参照してください。
FREE_10
FREE_20
FREE_30
空きスペース スレッショルド。可変長レコードを削除して空いたディスク領域を再利用するためのスレッショルド パーセンテージを設定することで、ファイルを認識する必要がなくなり、数ページにわたる可変長レコードの断片化を減らします。
空きスペース スレッショルドが大きいと、レコードの可変長部分の断片化が減少しパフォーマンスが向上します。ただし、ディスク領域がさらに必要になります。パフォーマンスを高くしたいときは、空きスペース スレッショルドを 30 パーセントに増やします。
DUP_PTRS
重複ポインターを予約します。将来追加するリンク重複キーにポインター スペースをプリアロケートします。リンク重複キーを作成するための重複ポインターがない場合、トランザクショナル データベース エンジンは繰り返し重複キーを作成します。
INCLUDE_SYSTEM_DATA
システム データ。ファイル作成時にシステム データを取り込むことによって、トランザクショナル データベース エンジンがファイルにログオンして処理を行うことを許可します。これは、一意のキーを含まないファイルで有効です。
NO_INCLUDE_SYSTEM_DATA
SPECIFY_KEY_NUMS
キー番号。トランザクショナル データベース エンジンが番号を自動的に割り当てるのではなく、特定の番号をキーに割り当てることができます。アプリケーションによっては、特定のキー番号を必要とするものがあります。
VATS_SUPPORT
可変長部割り当てテーブル(VAT)。VAT(レコードの可変長部分へのポインターの配列)を使用して、ランダム アクセスを加速化したり、データ圧縮時に使用される圧縮バッファーのサイズを制限します。詳細については、可変長部割り当てテーブルを参照してください。
簡素化を図るために、これらの定数は btrconst.h で定義され、C インターフェイスに合致しています。インターフェイスの中には、ほかの名前を使用したり、定数をまったく使用しないものがあります。ビット マスク、ファイル属性の 16 進値および 10 進値については、『Btrieve API Guide』を参照してください。

データ ファイルの例でこれらのファイル属性を使用していないのは、レコードが小さなサイズの固定長レコードであるからです。

ファイル属性の定義については、「ファイル タイプ」を参照してください。Create オペレーションにおけるファイル属性の詳細については、『Btrieve API Guide』を参照してください。

ファイル仕様およびキー仕様の構造体の作成

Create オペレーションを使用する場合は、ファイルとキーの仕様情報をデータ バッファーに渡します。以下の構造体では、社員データ ファイルの例を使用します。

表 15 ファイル仕様およびキー仕様のサンプル データ バッファー
説明
データ型1
バイト番号
値の例2
ファイル仕様
論理固定レコード長。(結合されたすべてのフィールドのサイズ:25 + 25 + 1 + 4 + 13 + 4)。手順については、論理レコード長の計算(トランザクショナル インターフェイス)を参照してください。3
Short Int4
0, 1
72
ページ サイズ。
ファイル仕様
Short Int
2, 3
 
6.0-9.0
512
6.0 以上
1,024
6.0-9.0
1,536
6.0 以上
2,048
6.0-9.0
3,072
3,584
6.0 以上
4,096
9.0 以上
8,192
9.5 以上
16,384
ほとんどのファイルでは最小サイズの 4096 バイトが最も効率的です。微調整を行う場合の詳細については、ページ サイズの選択 (トランザクショナル インターフェイス)を参照してください。
6.0 から 8.0 のファイル形式ではページ サイズ 512 の x 倍をサポートします。x は乗算の値が 4,096 以下になる数字です。
9.0 ファイル形式ではページ サイズ 8,192 もサポートすることを除けば、以前のバージョンと同じページ サイズをサポートします。
9.5 ファイル形式では、ページ サイズ 1,024 の 2 0 倍から 2 4 倍をサポートします。
9.5 形式のファイルを作成する場合、指定された論理ページ サイズがそのファイル形式で有効ならば、MicroKernel は指定値の次に大きな有効値があるかどうかを調べ、存在する場合はその値に切り上げます。それ以外の値やファイル形式の場合、オペレーションはステータス 24 で失敗します。古いバージョンのファイル形式では切り上げは行われません。
キー数。(ファイル内のキー数:2)
Byte
4
2
ファイル バージョン
Byte
5
0x60
バージョン 6.0
0x70
バージョン 7.0
0x80
バージョン 8.0
0x90
バージョン 9.0
0x95
バージョン 9.5
0x00
データベース エンジンのデフォルトを使用
予約済み(Create オペレーションでは使用しません。)
予約済み
6- 9
0
ファイル フラグ。ファイル属性を指定します。ファイルの例では、ファイル フラグを使用していません。
Short Int
10, 11
0
追加ポインター数。将来のキーの追加のために予約する重複ポインター数を設定します。ファイル属性で予約重複ポインターを指定する場合に使用します。
Byte
12
0
予約済み(Create オペレーションでは使用しません。)
予約済み
13
0
プリアロケート ページ数。事前に割り当てられるページ数を設定します。ファイル属性でページ プリアロケーションを指定する場合に使用します。
Short Int
14, 15
0
キー 0(ラスト ネーム)のキー仕様
キー ポジション。レコード内のキーの最初のバイトの位置を指定します。レコード内の最初のバイトは 1 です。
Short Int
16, 17
1
キー長。バイト単位でキーの長さを指定します。
Short Int
18, 19
25
キー フラグ。キー属性を指定します。
Short Int
20, 21
EXTTYPE_KEY + NOCASE_KEY + DUP + MOD
Create には使用しません。
Byte
22-25
0
拡張キー タイプ。キー フラグで「拡張キー タイプを使用する」を指定する場合に使用します。拡張データ型のうちの 1 つを指定します。
Byte
26
ZSTRING
ヌル値(レガシー ヌルのみ)。キー フラグで「ヌルキー(すべてのセグメント)」または「ヌルキー(任意のセグメント)」を指定する場合に使用します。キーの除外値を指定します。レガシー ヌルと真のヌルの概念については、「ヌル値」を参照してください。
Byte
27
0
Create には使用しません。
Byte
28, 29
0
手動割り当てキー番号。ファイル属性で「キー番号」を指定する場合に使用します。キー番号を割り当てます。
Byte
30
0
ACS 番号。キー フラグで「デフォルトの ACS を使用する」、「ファイル内の番号付きの ACS を使用する」または「名前付きの ACS を使用する」を指定する場合に使用します。使用する ACS 番号を指定します。
Byte
31
0
キー 1(社員 ID)のキー仕様
キー ポジション。(社員 ID は、ミドル イニシャルの後の最初のバイトから始まります。)
Short Int
32, 33
52
キー長。
Short Int
34, 35
4
キー フラグ。
Short Int
36, 37
EXTTYPE_KEY + MOD
Create には使用しません。
Byte
38-41
0
拡張キー タイプ。
Byte
42
INTEGER
ヌル値。
Byte
43
0
Create には使用しません。
Byte
44, 45
0
手動割り当てキー番号。
Byte
46
0
ACS 番号。
Byte
47
0
ページ圧縮のキー仕様
物理ページ サイズ5
Char
A
512
(デフォルト値)
1 特に指定がない場合、すべてのデータ型は符号なしです。
2 簡素化を図るため、数値以外の値の例は C アプリケーションの場合です。
3 可変長レコードを持つファイルの場合、論理レコード長はレコードの固定長部分のみを指します。
4 Short Integer(Short Int)は「リトル エンディアン」のバイト順、つまり、Intel 系のコンピューターが採用している下位バイトから上位バイトへ記録する方式で格納する必要があります。
5 ページ レベル圧縮でのみ使用します。ページ圧縮ファイル フラグ(表 6 を参照)と組み合わせて使用する必要があります。詳細については、ページ レベル圧縮を用いたファイルの作成を参照してください。

ページ レベル圧縮を用いたファイルの作成

Pervasive PSQL 9.5 以上では、Create オペレーションを使用してページ レベルの圧縮を用いたデータ ファイルを作成することができます。古いバージョンのデータ ファイルの場合は、論理ページを物理ページに割り当て、この割り当てをページ アロケーション テーブル(PAT)に格納します。物理ページのサイズは論理ページのサイズと同一です。

ファイルが圧縮されると、各論理ページが 1 つ以上の物理ページ単位に圧縮され、そのサイズは 1 論理ページよりも小さくなります。物理ページのサイズは、「物理ページ サイズ」属性(表 15 を参照)で指定されます。

ページ圧縮ファイル フラグ(表 6 を参照)は物理ページ サイズのキー仕様と組み合わせて使用され、ページ レベルの圧縮を適用したデータ ファイルを新規作成するよう MicroKernel へ通知します。論理ページ サイズと物理ページ サイズは次のように検証されます。

物理ページ サイズに指定された値は、論理ページ サイズに指定された値よりも大きくすることはできません。物理ページ サイズに指定された値の方が大きい場合、MicroKernel は論理ページ サイズと同じになるようその値を切り捨てます。論理ページ サイズは物理ページ サイズの倍数になっていなければなりません。倍数でない場合、その論理ページ サイズの値は物理ページ サイズの値のちょうど倍数になるよう切り捨てられます。このような操作の結果として、論理ページ サイズと物理ページ サイズの値が同じになった場合、ページ レベルの圧縮はこのファイルに適用されません。

Create オペレーションの呼び出し

Create オペレーション(14)では、以下の値が必要です。

C における API 呼び出しは次のようになります。

Create オペレーション

/* データ バッファー構造体の定義 */ 
typedef struct 
{ 
 BTI_SINT recLength; 
 BTI_SINT pageSize; 
 BTI_SINT indexCount; 
 BTI_CHAR reserved[4]; 
 BTI_SINT flags; 
 BTI_BYTE dupPointers; 
 BTI_BYTE notUsed; 
 BTI_SINT allocations; 
} FILE_SPECS; 
 
typedef struct 
{ 
 BTI_SINT position; 
 BTI_SINT length; 
 BTI_SINT flags; 
 BTI_CHAR reserved[4]; 
 BTI_CHAR type; 
 BTI_CHAR null; 
 BTI_CHAR notUsed[2]; 
 BTI_BYTE manualKeyNumber; 
 BTI_BYTE acsNumber; 
} KEY_SPECS; 
 
typedef struct 
{ 
 FILE_SPECS fileSpecs; 
 KEY_SPECS  keySpecs[2]; 
} FILE_CREATE_BUF; 
/* データ バッファーの作成 */ 
FILE_CREATE_BUF databug; 
memset (databuf, 0, size of (databuf)); /* databuf の
初期化 */ 
dataBuf.recLength = 72; 
dataBuf.pageSize = 4096; 
dataBuf.indexCount = 2; 
dataBuf.keySpecs[0].position = 1; 
dataBuf.keySpecs[0].length = 25; 
dataBuf.keySpecs[0].flags = EXTTYPE_KEY + NOCASE_KEY 
+ DUP + MOD; 
dataBuf.keySpecs[0].type = ZSTRING; 
dataBuf.keySpecs[1].position = 52; 
dataBuf.keySpecs[1].length = 4; 
dataBuf.keySpecs[1].flags = EXTTYPE_KEY; 
dataBuf.keySpecs[1].type = INTEGER; 
/* ファイルの作成 */ 
strcpy((BTI_CHAR *)keyBuf, 
"c:¥¥sample¥¥sample2.mkd"); 
dataLen = sizeof(dataBuf); 
status = BTRV(B_CREATE, posBlock, &dataBuf, 
&dataLen, keyBuf, 0); 

Create Index オペレーション

あらかじめキーが定義されているファイルを作成すると、挿入、更新、または削除のたびにインデックスにデータが設定されます。これは、ほとんどのデータベース ファイルに必要です。しかし、読み取る前にデータが完全に取り込まれる類のデータベース ファイルがあります。これらには、テンポラリ ソート ファイルや、製品の一部として提供されるデータ実装済みのファイルが挙げられます。

このようなファイルの場合、レコードが書き込まれた後に Create Index(31)でキーを作成する方が処理が速くなる可能性があります。レコードの挿入をより速く実行できるように、インデックスを定義せずにファイルを作成する必要があります。その後、Create Index オペレーションによって、より効率的な方法でキーをソートし、インデックスを作成します。

このように作成されたインデックスも効率が良く、高速なアクセスができます。インデックス ページはキー順に読み込まれるので、Create Index(31)の実行時、トランザクショナル データベース エンジンは各ページの終わりに空き領域を残す必要がありません。各ページは、100% 近くまでレコードが書き込まれます。それに対して、Insert(2)または Update(3)オペレーションでインデックス ページにレコードを書き込む場合、インデックス ページは半分に分割され、レコードの半分は新しいページにコピーされます。このプロセスにより、平均的なキー ページは約 50~65% まで満たされます。インデックス バランスを使用すると、65 ~ 75% まで満たされる場合があります。

Create Index(31)オペレーションのもう 1 つの利点として、作成された新しいキー ページはすべてファイルの終わりにまとめて書き込まれます。これは、大きなファイルの場合、読み取り処理間で読み取りヘッドの移動距離が短くなるということです。

この手法では、レコードが数千件しかない小さなファイルの場合、処理速度が上がらない可能性があります。このオペレーションの利点を生かすには、ファイルにさらに大きなキー フィールドが必要になります。さらに、すべてのキー ページをトランザクショナル インターフェイス キャッシュに収容できる場合、この手法では速度は向上しません。しかし、常にキー ページのほんの一部しかキャッシュ内にないのであれば、多くの余分なキー ページの書き込みが省かれます。100 万件のレコードを含むファイルも、この方法を使用すると、何日もかからず数時間または数分で作成できます。Create Index(31)では、ファイル内のキー ページ数が多いほど、一度に 1 レコードずつ挿入する場合よりも高速にインデックスを作成できます。

つまり、Pervasive PSQL ファイルを最初から読み込む場合、すべてのキー ページを保持するためのキャッシュ メモリが不足することを避けることが重要です。その場合は、Create(14)を使用してインデックスを付けずにファイルを作成し、すべてのデータ レコードが挿入されたときに Create Index(31)を使用します。

これらのオペレーションの詳細については、『Btrieve API Guide』を参照してください。


データ ファイルについて (トランザクショナル インターフェイス)

論理レコード長の計算(トランザクショナル インターフェイス)