【IRIS/Cache】グローバルざっくり解説#4 ノードの順番を変えるとデータ量は変わるの?

本記事は、ノードの配列とデータ量の関係について解説します。

※この記事は下記の方向けになります。
  • ObjectScript初心者の方
  • グローバル構造について詳しく知りたい方
  • データ・ブロックの仕様について知りたい方

Q. ノードの順番を変えるとデータ量は変わるの?

A. 変わります。

「えっ、本当に!?」

と思われた方は、ぜひこの記事を最後までご覧ください。
きっと、あなたの認識が少しだけ変わるはずです。

データ・ブロックの中身

管理ポータル画面を開きグローバルを表示すると、下記の様に見慣れた構成で表示されます。

今更ですが、表示の構成としては「グローバルの名前」「各ノードの値」「各ノードに対するデータ」の3要素になります。

また、ノードが自動でソートされているのも、お馴染みですね。

管理ポータルで表示されるグローバル構造

ただし、データ・ブロックに格納される値は異なります。

では、データ・ブロックにはどのように格納されているのでしょうか。

データ・ブロックには、下記赤枠内にある「2回目以降のグローバル名」と「重複しているノード」が省略して格納されます。

下記の例では、赤枠の項目になります。

実際にデータ・ブロックに格納される情報(赤枠以外が格納される)

つまり、選択性(Selectivity)の高いノードと、選択性の低いノードがある場合、選択性の高い順に並べた方が、省略できる値が増える為、全体のデータ量が小さくなります。

逆に、選択性の低い順に並べると省略できる項目が減るため、額面通りのデータ量になります。

仕様が分かったので、検証を行いましょう。

検証

下記2つのプロパティを持つデータ・クラスがあります。

Class developer.data.DataCheck Extends (%Persistent, %Populate)
{
Index idx On (sei, name);

Property sei As %String(POPSPEC = "ValueList("",藤原,近衛,九条"")");

Property name As %String(POPSPEC = "StringMin(30,30)");
}

Populate関数で10,000件のデータを作成します。
 ※Pupulateの詳細は下記記事を参照してください。

作成されたデータを確認すると下記になります。

プロパティ名選択性値選択性データ例
sei33.3333%高い藤原 or 近衛 or 九条(3種のみ)
name0.0100%低いランダムな文字列(ほぼ全てが不一致)

データ量が変化を簡単に検証するには、インデックスの組み換えを行うと良いです。

インデックス「idx」を選択性の異なる2つのプロパティの組み合わせで検証します。
下記2パターンを作成し、そのデータ量を測定してみましょう。

  • Index idx On (sei, name); // 選択性が高い -> 低いの組み合わせ
  • Index idx On (name, sei); // 選択性が低い -> 高いの組み合わせ

データ量の比較

データ量の比較の比較を行うのであれば、^%GSIZEを使用します。

※詳細は下記記事を参照してください。

今回は、グローバル「^developer.data.DataCheckI」を詳細モードで確認します。

zn "%SYS"
 
%SYS>d ^%GSIZE
 
 
Directory name: d:\iris\mgr\ => D:\IRISDB\SAMPLE-DATA
 
All Globals? No => No
Global ^developer.data.DataCheckI
Global ^
1 global selected from 89 available globals.
 
Show details?? No => yes
Device:
Right margin: 80 =>

結果を比較します。

項目ブロック数データ量(バイト)PackingContig.
sei, nameの組み合わせ62370,57673%2
name, seiの組み合わせ78445,43670%1

ブロック数では16ブロック、バイト数では73kbの差が出ました。
 ※充填率の差に関しては、今回の検証対象外とさせて下さい。

この差は先ほど記述した通り、「グローバル名」・「藤原/近衛/九条の各重複ノード」が省略して格納された事によります。

とは言え、インデックスのノードの組み合わせは、参照する項目にも依存します。
検索する項目、選択性の高/低をよく検討しつつ、適切にインデックスを組めれば良いですね。

nameが判別している状態で検索を行うのであれば、「name, sei」の組み合わせの方がより早く検索する事が可能です。

ノードの配置順でデータ量が変わる事は確認しました。

では、ループの速度はどうでしょう・・・?

次は、ループ速度を検証してみたいと思います。

ループ速度を検証する

速度差を検証するため、レコード数を増やしてループ速度を検証してみたいと思います。

下記簡単な関数を作成して、検証してみたいと思います。

ClassMethod loop()
{
	s start = $zh
	
	s (key1, key2) = ""
	f {
		s key1 = $o(^developer.data.DataCheckI("idx", key1))
		q:key1=""
		
		f {
			s key2 = $o(^developer.data.DataCheckI("idx", key1, key2))
			q:key2=""
		}
	}
	
	w $zh - start
}

【実行結果】
sei, nameの組み合わせ:0.358816
name, seiの組み合わせ:0.636474

選択性の高い->低いの組み合わせの方が、ループ速度が速い結果となりました。

この差は、なぜ生まれるのでしょうか?
各ブロックの参照回数を比較しつつ確ししてみます。

【Index sei, nameの組み合わせ】

処理時間GloRefDisc
Bpn
Disc
Data
Buf
Dir
Buf
Data
s key1 = $o(^[I](“idx”, key1))0.01310441110
s key2 = $o(^[I](“idx”, key1, key2))0.470166100003062401
GloRef=グローバル参照回数
Disc=ディスクアクセス, Buf=グローバル・バッファ
Dir=ディレクトリ・ブロック, Bpn=下部ポインタ・ブロック, Data=データ・ブロック

【Index name, seiの組み合わせ】

処理時間GloRefDisc
Bpn
Disc
Data
Buf
Dir
Buf
Data
s key1 = $o(^[I](“idx”, key1))0.486492100001174110
s key2 = $o(^[I](“idx”, key1, key2))0.3255222000000001

両者の比較を行うと、下記が言えると考えます。

  • データ量が少ないため、ディスクアクセスへのアクセス回数が異なる。
  • ループ回数が大きく異なる

ループ数の差に関しては、割とイメージしやすいです。
上位ノードの数が多いと、それだけループ数も増えますね。

まとめ

これまでの結果をまとめると下記になります。

まとめ
  • 選択性の高い順からノードを並べると、データ量が少なくなる
  • 選択性の高い順からノードを並べると、ループ処理が早くなる

ただしノードの組み方は、そのグローバルの用途に沿って組み上げるのが第一優先ではあります。

どの順番でも問題ない場合に限り、本記事の内容を参考にしてみて下さい。

以上、ノードの並び順と [データ量・ループ速度] の関係について解説致しました。
本記事が、皆さまの実務や学びの中で、少しでもお役に立てれば幸いです。