btree index (10)

_bt_buildadd

sortしてからbtree indexを作成するとき、pageにアイテムを登録する関数。
pageを作成中のleaf pageの構造は以下のようになる。テーブルのpage構造とほとんど同じだが、linp0とかlastの所に細工がしてある。

(nbtsort.cより)
 * A leaf page being built looks like:
 *
 * +----------------+---------------------------------+
 * | PageHeaderData | linp0 linp1 linp2 ...           |
 * +-----------+----+---------------------------------+
 * | ... linpN |                                      |
 * +-----------+--------------------------------------+
 * |     ^ last                                       |
 * |                                                  |
 * +-------------+------------------------------------+
 * |             | itemN ...                          |
 * +-------------+------------------+-----------------+
 * |          ... item3 item2 item1 | "special space" |
 * +--------------------------------+-----------------+

linp0はhigh keyを登録するために空けておき、linp1から順にItemIdを登録していき、item1から対応するBTItemを登録していく。pageの使用量がしきい値を超え、新しいアイテムが登録できなくなったら、次の処理を行う。

(1)_bt_blnewpageで新しいページ(npage)を割り当てる
(2)それまで使っていたページ(opage)の一番最後のアイテム(itemN)を、npageの先頭のアイテムとして登録する。(npageのlinp1, item1へ登録される)

        ii = PageGetItemId(opage, last_off);
        obti = (BTItem) PageGetItem(opage, ii);
        _bt_sortaddtup(npage, ItemIdGetLength(ii), obti, P_FIRSTKEY);

(3)linp0にlinpNの情報をコピーする。これでopageのhigh keyはitemNになる。

        hii = PageGetItemId(opage, P_HIKEY);
        *hii = *ii;

(4)linpNを未使用にする。linpNのLP_USEDフラグを外して、pageのpd_lowerをlinpNの前(図のlastの位置)へ戻すことにより実現している。

        ii->lp_flags &= ~LP_USED;
        ((PageHeader) opage)->pd_lower -= sizeof(ItemIdData);

(5)opage,npageの左右のリンクを設定する。
(6)_bt_blwritepageでopageをディスクに出力する。opageはこれ以降変更されない
(7)新しいBTItemを追加する

(2)-(4)の処理によって、opageのItemNはデータではなくhigh keyとして使われる。Index ItemとしてのItemNはnpageの先頭に登録されている。また、leaf pageが一番右のpageだった場合は、linp0はhigh keyではなく先頭のItemを指す必要がある。このため、index作成の最後のほうで、_bt_slideleftを実行し、linp1〜linpNを一つずつ前へずらしている。

_bt_pagestate

BTPageStateを作成する。BTPageStateはbtree indexの作成中の各レベルの情報を管理する。(各レベルにつき1つ作成される)

BTPageStateのbtps_fullで各pageが使用できる量を設定する。leaf pageは90%まで、non-leaf pageは70%まで利用できるように設定している。

    /* set "full" threshold based on level.  See notes at head of file. */
    if (level > 0)
        state->btps_full = (PageGetPageSize(state->btps_page) * 3) / 10;
    else
        state->btps_full = PageGetPageSize(state->btps_page) / 10;