グローバルのCachéビットマップインデックス

CachéオブジェクトDBMSは、ビットマップインデックスとビットスライスインデックスをサポートしています。 Cachéクラスでの使用は非常に簡単です。インデックスの説明でBitmapまたはBitslice属性を指定するだけで十分であり、一部のSQLクエリのパフォーマンスは劇的に向上します。 しかし、それはどのように機能しますか?

この記事では、ビットマップインデックスの構造、任意のグローバル構造でのビットマップインデックスの作成方法、ビットロジック関数の使用方法、およびCachéでNoSQLを実行する際の効果的な使用方法について説明します。



事前オブジェクト時間以来、グローバルで関心のあるレコードを迅速に検索するためのアプリケーションを開発するとき、最も頻繁にフォームのインデックスが構築されました



セット ^インデックス( "Property" value id )= ""



このようなインデックスを使用すると、対象のプロパティに特定の値があるレコードを簡単かつ迅速に検索できます。



set id = "" for set id = $ order (^ Index( "Property" value id )) quit id = "" write id、!



Propertyプロパティの値がvalueであるすべてのレコードの識別子を提供します。たとえば、次のコードを使用して、このプロパティ値を持つレコードの存在を確認できます。



if $ data (^ Index( "Property" value ))> 1 {

"id" _ $ order (^ Index( "Property" value "" ))を 書き込み ます _ "with" _ value _ "exists" }

その他 {

「次のものがあるレコード」 _ _ 「存在しない 」を 書き込む }



「I」ロジックによって結合された複数の条件を同時に満たすレコードを効率的に検索するためのアルゴリズムを考案することは難しくありません。 しかし、より複雑なクエリの場合は、より複雑なアルゴリズムを開発(およびデバッグ)するか、データベース内のすべてのレコードを直接列挙するためにインデックスの使用を放棄する必要がありました。



革命的な変更は、Cachéでの本格的なビット関数の出現でした。 $ bit ()、 $ bitlogic ()、 $ bitfind ()、 $ bitcount ()です。 次の形式のビットマップインデックスを構築できます。



set $ bit (^ Index( "Property" value )、 id )= 1



もちろん、ビット文字列の長さは256Kに制限されているため、実際のアプリケーションではビットマップインデックスは1ビット文字列ではなく配列に配置する必要があります。

$ bitlogic()関数は、任意の興味深いクエリを満たすレコードのサンプルに対応するインデックスから結果のビットマップインデックスを簡単に形成することを可能にし、$ bitcount()はサンプルに含まれるレコードの数を決定し、$ bitfind()は結果のサンプル。



たとえば、「Pr1」プロパティの値が「A」または「B」で、「Pr2」プロパティの値が「C」であるレコードを収集します。



set ^ mtemp.resbitmap = $ bitlogic (^ Index( "Pr1" "A" )| ^ Index( "Pr1" "B" ))

set ^ mtemp.resbitmap = $ bitlogic (^ mtemp.resbitmap&^ Index( "Pr2" "C" ))



そしてそれらにIDを与えます:



if ' $ bitcount(^ mtemp.resbitmap) write "No records found" 、!

それ以外の場合は 、set id = $ bitfind (^ mtemp.resbitmap、1、 id )の 場合、 set id = 0 quit : ' id write id 、!



これは、Cachéのビット関数から絞り込めるだけではありません。 グループ化関数の値(合計、算術平均、最小、最大)をすべて同じように計算するには、サンプルに含まれるすべてのレコードを並べ替える必要がありましたが、十分なサンプルサイズでは高速ではありませんでした。 ただし、ビットマップインデックスの構造を少し変更すると、プロパティ値が整数または固定小数点の場合、この手順も大幅に高速化されます。

この変更の本質は、プロパティ値の各ビットに個別のビットマップインデックスを構築することです。 このような構造はビットスライスと呼ばれます。



set $ bit (^ Index( "Property" N )、 id )= NthBitOfValue



実際にも、ビット文字列の代わりに配列が使用されます。

ビットスライスを使用する場合、たとえば「より多く」または「より少ない」制限を検索するなど、少し複雑になりますが、グループ化関数の計算で得られるメリットはこの不便さを大きく上回ります。 実際、選択したレコードの対象プロパティの値の合計を計算するために、レコードを循環する必要はなくなりました。 すべてのビットの結果のビットマップインデックスの対応する重み$ bitcount()で対象のプロパティの値を合計するだけで十分です。 十分なサンプルサイズがあれば、パフォーマンスの向上は、誇張と呼ばれる誇張なしで実現できます。



クラスコード
///ビットマップおよびビットスライスインデックスを作成および操作するための一連のメソッド

///

///ビットマップインデックスの構造

///配列(値)の形式の配列、その要素は

///レコード番号に対応する位置に1を含むビット文字列、

///いくつかのパラメータが値valueをとる、

///最大長$$$ MAXBITLENGTHの文字列の配列に分割

///レコード番号-1から、配列要素-0から、

///(以降、簡潔にするため、ビットマップ)。

///充填の例

///エントリにidfactパラメータ番号を持たせますparはvalです

/// idf0 = idfact-1 \ $$$ MAXBITLENGTHを設定、idf1 = idfact-1#$$$ MAXBITLENGTH + 1

/// $ビットを設定(^ BM( "I"、par、val、idf0)、idf1)= 1

/// $ビットを設定(^ BM( "EXIST"、idf0)、idf1)= 1

///まず、既存のエントリのインデックスが便利です。

///論理削除を簡単に実行できます。次に、

///を使用せずにリポジトリ内のレコード数を検索できるようにします

///他の構造へのアクセス、これは正しいために必要です

/// BMNotプロシージャの操作(以下を参照)

/// beatleysインデックスの構造:

///ビットマップインデックスの配列。 配列の最初の要素-文字インデックス

///値、2番目—値の最下位ビットのインデックス(1/0)、3番目—

///最後から2番目のビットのインデックス(2/0)など

///

///充填の例

///エントリ番号idfactパラメータparに整数を持たせる

/// valの値

/// idf0 = idfact-1 \ $$$ MAXBITLENGTHを設定、idf1 = idfact-1#$$$ MAXBITLENGTH + 1

/// val = $$ CvtToBin(val)を設定

/// for ix = 1:1:$ length(val)set:$ extract(val、ix)$ bit(^ BM( "S"、par、ix、idf0)、idf1)= 1

///壊滅的な落下を避けるための大量充填時

///パフォーマンス、対応するフラグメントをオーバーレイすることをお勧めします

///関数のコード$ sortbegin(^ BM)および$ sortend(^ BM)

///指定された制限に応じたファクトの選択および受信した計算用

///グループ化関数「sum」、「maximum」、および「minimum」のサンプル

///関数BSSum()、BSMax()およびBSMin()が対象

クラスUser.BitMapSlice Extends%RegisteredObject [ ProcedureBlock ]

{



///ビットマップとビットスライスを保存するグローバルな名前($ na)

///デフォルト値は「^ BM」です

プロパティ BMGLOB As%String TRUNCATE = 1 )[ InitialExpression = "^ BM" ];



///使用する$ビット文字列の最大長

パラメーター MAXBITLENGTH = 64000 ;



///グローバルグローバルサブノードの名前($ na())を作成して返します

///中間ビットマップを保存するため

ClassMethod GetNewTMP() As%文字列

{

quit $ name (^ CacheTemp( "BM" $ job _ $ zutil (110)、 $ increment (^ CacheTemp( "BM" $ job _ $ zutil (110)))))

}



///このプロセスによって作成されたすべての一時的なサブノードを削除します

ClassMethod KillAllTMP()

{

kill ^ CacheTemp( "BM" $ job _ $ zutil (110)) quit

}



///ビットマップの操作

///以下、柔軟性、ビットインデックス、

///配列とスライスは名前で渡される($ na())

///

/// posに続く位置を1ビットで見つける

/// bm-名前で渡されるビットマップ

メソッド BMOrder( bm As%String pos As%String As%String

{

set sub = pos \ .. #MAXBITLENGTH ix = $ bitfind $ get (@ bm @( sub ))、1、 pos #.. #MAXBITLENGTH +1)

quit ix sub * .. #MAXBITLENGTH + ix

set sub = $ order (@ bm @( sub )) quit : ' sub set ix = $ bitfind $ get (@ bm @( sub ))、1) quit ix

quit ix sub * .. #MAXBITLENGTH + ix

「」を 終了

}



/// bmdest = bmdest&bmsrc

メソッド BMAnd( bmdest As%String bmsrc As%String

{

set sub1 = $ order (@ bmdest @( $ char (0))、-1)、 sub = $ order (@ bmsrc @( $ char (0))、-1)

セット sub < sub1 sub = sub1

for ix = 0:1: sub set $ data (@ bmdest @( ix ))& $ data (@ bmsrc @( ix ))@ bmdest @( ix )= $ bitlogic (@ bmdest @( ix )&@ bmsrc @( ix )) kill : ' $ data (@ bmsrc @( ix ))@ bmdest @( ix

やめる

}



/// bmdest = bmdest | bmsrc

メソッド BMOr( bmdest As%String bmsrc As%String

{

set sub1 = $ order (@ bmdest @( $ char (0))、-1)、 sub = $ order (@ bmsrc @( $ char (0))、-1)

セット sub < sub1 sub = sub1

for ix = 0:1: sub set $ data (@ bmsrc @( ix ))@ bmdest @( ix )= $ select $ data (@ bmdest @( ix )): $ bitlogic (@ bmdest @( ix ) | @ bmsrc @( ix ))、1:@ bmsrc @( ix ))

やめる

}



メソッド BMNot( bm As%String

{

set maxblk = $ order (@(.. BMGLOB )@( "EXIST" "" )、-1)、 blklen = $ bitcount (@(.. BMGLOB )@( "EXIST" maxblk ))

for ix = maxblk :-1:0 set blk = $ get (@ bm @( ix )) set $ bitcount blk )< blklen $ bit blk blklen )= 0 set @ bm @( ix )= $ bitlogic 〜blk )、 blklen = .. #MAXBITLENGTH

do .. BMAnd bm $ name (@(.. BMGLOB )@( "EXIST" ))))

やめる

}



///配列内の単位ビットの数を返します

メソッド BMCount( bm As%String As%Integer

{

ix = "" bmcret = 0に設定

set ix = $ order (@ bm @( ix )) quit ix '= + ix set bmcret = bmcret + $ bitcount (@ bm @( ix )、1)

bmcretを 終了

}



///ビットマップインデックスvbmsrcから選択をbmdestビットマップに配置し、

///パラメータ値はvalです

///

メソッド BMEq( bmdest As%String vbmsrc As%String val As%String

{

kill @ bmdest merge @ bmdest = @ vbmsrc @( val

やめる

}



///ビットマップインデックスvbmsrcから選択をbmdestビットマップに配置し、

///パラメータ値がvalと等しくない場合

メソッド BMNe( bmdest As%String vbmsrc As%String val As%String

{

do .. BMEq bmdest vbmsrc val do .. BMNot bmdest

やめる

}



///ビットマップインデックスvbmsrcから選択をbmdestビットマップに配置し、

///パラメータ値が小さい(ソートされた)val

/// bmdest:= U(vbmsrc(v):v <val)

メソッド BMLt( bmdest As%String vbmsrc As%String val As%String

{

kill @ bmdest set ix = val

set ix = $ order (@ vbmsrc @( ix )、-1) quit ix = "" do .. BMOr bmdest $ name (@ vbmsrc @( ix )))

やめる

}



/// BMLt()に似ていますが、「より小さいか等しい」

メソッド BMLe( bmdest As%String vbmsrc As%String value As%String

{

kill @ bmdest merge @ bmdest = @ vbmsrc @( val set ix = val

set ix = $ order (@ vbmsrc @( ix )、-1) quit ix = "" do .. BMOr bmdest $ name (@ vbmsrc @( ix )))

やめる

}



/// BMLeに似ていますが、「以上」

メソッド BMGe( bmdest As%String vbmsrc As%String val As%String

{

kill @ bmdest merge @ bmdest = @ vbmsrc @( val set ix = val

set ix = $ order (@ vbmsrc @( ix )) quit ix = "" do .. BMOr bmdest $ name (@ vbmsrc @( ix ))))

やめる

}



///同様に、min以上max以下の値

メソッド BMGeLe( bmdest As%String vbmsrc As%String min As%String max As%String

{

kill @ bmdest merge @ bmdest = @ vbmsrc @( min set ix = min

set ix = $ order (@ vbmsrc @( ix )) quit ix ]] max quit ix = "" do .. BMOr bmdest $ name (@ vbmsrc @( ix ))))

やめる

}



/// BMGe()に似ていますが、「厳密に大きい」

メソッド BMGt( bmdest As%String vbmsrc As%String val As%String

{

kill @ bmdest set ix = val

set ix = $ order (@ vbmsrc @( ix )) quit ix = "" do .. BMOr bmdest $ name (@ vbmsrc @( ix ))))

やめる

}



///同様に、minより大きくmaxより小さい値

メソッド BMGtLt( bmdest As%String vbmsrc As%String min As%String max As%String

{

kill @ bmdest set ix = min

set ix = $ order (@ vbmsrc @( ix )) quit max ']] ix quit ix = "" do .. BMOr bmdest $ name (@ vbmsrc @( ix )))

やめる

}



///同様に、min以上max以下の値

メソッド BMGeLt( bmdest As%String vbmsrc As%String min As%String max As%String

{

kill @ bmdest merge @ bmdest = @ vbmsrc @( min set ix = min

set ix = $ order (@ vbmsrc @( ix )) quit max ']] ix quit ix = "" do .. BMOr bmdest $ name (@ vbmsrc @( ix )))

やめる

}



///同様に、minより大きくmax以下の値

メソッド BMGtLe( bmdest As%String vbmsrc As%String min As%String max As%String

{

kill @ bmdest set ix = min

set ix = $ order (@ vbmsrc @( ix )) quit ix ]] max quit ix = "" do .. BMOr bmdest $ name (@ vbmsrc @( ix ))))

やめる

}



///ビットスライスデータの操作

///整数値をテキストビット文字列に変換します

/// {sign、1,2,4、...、2 ** N}

ClassMethod CvtToBin( value As%Integer As%String

{

設定 = $ fnumber (+ value "" 、0)、 res =( value <0)

for quit : ' value set res = res _( value #2)、 value = value \ 2

解像度を やめる

}



/// $ lbビットリスト(符号、1、2、4、... 2 ** N)を整数に変換します

ClassMethod CvtFromSlice( slice As%String As%整数

{

res = 0に 設定

for i = $ listlength slice ):-1:2 set res = res + res set res = res + $ listget slice i 、0)

quit $ select $ listget slice ):- res 、1: res

}



/// vbs bitliceのpos位置からビットをリストに入れます($ lb())

メソッド GetSlice( vbs As%String pos As%Integer As%String

{

set sub = pos \ .. # MAXBITLENGTH ix = pos -1#.. #MAXBITLENGTH +1

for i = 1:1: $ order (@ vbs @( "" )、-1) set $ list slice i )= $ bit $ get (@ vbs @( i sub )))、 ix

スライスを 終了

}



/// bmdestビット配列にvbsビットスライスインデックスからのサンプルを配置し、

///パラメータ値はvalです

メソッド BSEq( bmdest As%String vbs As%String val As%Integer

{

set bswork = .. GetNewTMP () set vbit = .. CvtToBin val

kill @ bmdest merge @ bmdest = @(.. BMGLOB )@( "EXIST"

set maxbit = $ order (@ vbs @( "" )、-1) set maxbit < $ length vbit maxbit = $ length vbit

for ix = 1:1: maxbit kill @ bswork merge @ bswork = @ vbs @( ix do : ' $ extract vbit ix ).. BMNot bswork do .. BMAnd bmdest bswork

@bswork quitを終了

}



/// bmdestビット配列にvbsビットスライスインデックスからのサンプルを配置し、

///パラメータの値がval以上の場合

メソッド BSGe( bmdest As%String vbs As%String val As%Integer

{

do .. BSLt bmdest vbs val )、.. BMNot bmdest quit

}



/// bmdestビット配列にvbsビットスライスインデックスからのサンプルを配置し、

///パラメータ値がvalと等しくない場合

メソッド BSNe( bmdest As%String vbs As%String val As%Integer

{

do .. BSEq bmdest vbs val )、.. BMNot bmdest

やめる

}



/// bmdestビット配列にvbsビットスライスインデックスからのサンプルを配置し、

///パラメータ値がvalより大きい場合

///

メソッド BSGt( bmdest As%String vbs As%String val As%Integer

{

do .. BSLe bmdest vbs val )、.. BMNot bmdest quit

}



/// bmdestビット配列にvbsビットスライスインデックスからのサンプルを配置し、

///パラメータの符号は符号です(ゼロは正と見なされます)

メソッド BSSign( bmdest As%String vbs As%String sign As%Integer

{

set bswork = .. GetNewTMP () kill @ bmdest

merge @ bmdest = @(.. BMGLOB )@( "EXIST" )、@ bswork = @ vbs @(1)

do $ get sign ) '<0 .. BMNot bswork do .. BMAnd bmdest bswork

@bswork quitを終了

}



/// bmdestビット配列にvbsビットスライスインデックスからのサンプルを配置し、

///パラメータ値がval以下の場合

メソッド BSLe( bmdest As%String vbs As%String val As%Integer

{

tmpLe = .. GetNewTMP ()を 設定し ます

do .. BSLtAbs bmdest vbs val )、.. BSSign tmpLe vbs 、-1)

if val '<0 do .. BMOr bmdest tmpLe )、.. BSEq tmpLe vbs val )、.. BMOr bmdest tmpLe if 1

それ以外の場合 .. BMNot bmdest )、.. BMAnd bmdest tmpLe

kill @ tmpLe quit

}



/// bmdestビット配列にvbsビットスライスインデックスからのサンプルを配置し、

///パラメータ値がvalより小さい場合

メソッド BSLt( bmdest As%String vbs As%String val As%Integer

{

tmpLt = .. GetNewTMP ()を 設定し ます

do .. BSLtAbs bmdest vbs val )、.. BSSign tmpLt vbs 、-1)

if val '<0 do .. BMOr bmdest tmpLt if 1

ELSE do .. BMNot bmdest )、.. BMAnd bmdest tmpLt )、.. BSNe tmpLt vbs val )、.. BMAnd bmdest tmpLt

kill @ tmpLt quit

}



/// bmdestビット配列にvbsビットスライスインデックスからのサンプルを配置し、

///パラメータ値がval1以上val2以下

メソッド BSGeLe( bmdest As%String vbs As%String val1 As%Integer val2 As%Integer

{

tmpGeLe = .. GetNewTMP ()を 設定し ます

do .. BSGe bmdest vbs val1 )、.. BSLe tmpGeLe vbs val2 )、.. BMAnd bmdest tmpGeLe

kill @ tmpGeLe quit

}



/// vbsビットスライスインデックスから選択範囲をbmdestビットマップに配置し、

///パラメータ値がval1以上val2より小さい場合

メソッド BSGeLt( bmdest As%String vbs As%String val1 As%Integer val2 As%Integer

{

tmpGeLt = .. GetNewTMP ()を 設定し ます

do .. BSGe bmdest vbs val1 )、.. BSLt tmpGeLt vbs val2 )、.. BMAnd bmdest tmpGeLt

kill @ tmpGeLt quit

}



/// bmdestビット配列にvbsビットスライスインデックスからのサンプルを配置し、

///パラメータ値がval1より大きく、val2以下

メソッド BSGtLe( bmdest As%String vbs As%String val1 As%Integer val2 As%Integer

{

tmpGtLe = .. GetNewTMP ()を 設定し ます

do .. BSGt bmdest vbs val1 )、.. BSLe tmpGtLe vbs val2 )、.. BMAnd bmdest tmpGtLe

kill @ tmpGtLe quit

}



/// vbsビットスライスインデックスから選択範囲をbmdestビットマップに配置し、

///パラメータ値がval1より大きく、val2より小さい場合

メソッド BSGtLt( bmdest As%String vbs As%String val1 As%Integer val2 As%Integer

{

tmpGtLt = .. GetNewTMP ()を 設定し ます

do .. BSGt bmdest vbs val1 )、.. BSLt tmpGtLt vbs val2 )、.. BMAnd bmdest tmpGtLt

kill @ tmpGtLt quit

}



/// vbsビットスライスインデックスから選択範囲をbmdestビットマップに配置し、

///絶対値のパラメーター値がvalより小さい場合

メソッド BSLtAbs( bmdest As%String vbs As%String val As%Integer

{

set bswork = .. GetNewTMP ()、 test = .. GetNewTMP ()

kill @ bmdest set vbit = .. CvtToBin val )、 ixmax = $ order (@ vbs @( "" )、-1)

kill @ test merge @ test = @(.. BMGLOB )@( "EXIST"

if ixmax < $ length vbit {

merge @ bmdest = @ test

} else {

ix = ixmaxの場合 :-1:2 {

kill @ bswork merge @ bswork = @ vbs @( ix

.. BMNot bswork )、.. BMAnd bswork test

do $ extract vbit ix ).. BMOr bmdest bswork )、.. BMNot bswork

.. BMAnd テスト bswork

}

}

@testを強制 終了 、@ bsworkを 終了

}



/// beatleysインデックスのグループ化関数

///最大値を返します(オプションのパラメーター付き

/// bsmin '= 0-minimum)vbsビットスライスインデックスからビットマップを選択するため

メソッド BSMax( vbs As%String ビットマップ As%String bsmin As%String As%Integer

{

set bsmin = '' $ get bsmin )、 bswork = .. GetNewTMP ()

resBSM = .. GetNewTMP ()、 tmpBSM = .. GetNewTMP ()を設定します

merge @ resBSM = @ vbs @(1) do : ' bsmin .. BMNot resBSM do .. BMAnd resBSM ビットマップ

if .. BMCount resBSM set min = 0

ELSE set min = 1 kill @ resBSM merge @ resBSM = @ vbs @(1) do bsmin .. BMNot resBSM do .. BMAnd resBSM ビットマップ

for ix = $ order (@ vbs @( "" )、-1):-1:2 {

@ tmpBSMを強制終了 、@ bsworkを マージ @ tmpBSM = @ resBSM 、@ bswork = @ vbs @( ix

do min .. BMNot bswork do .. BMAnd tmpBSM bswork

if .. BMCount tmpBSM kill @ resBSM merge @ resBSM = @ tmpBSM

}

set pos = .. BMOrder resBSM 、0) quit : ' pos 0

set val = .. CvtFromSlice (.. GetSlice vbs pos ))

kill @ bswork 、@ resBSM 、@ tmpBSM quit val

}



メソッド BSMin( vbs As%String ビットマップ As%String As%Integer

{

quit .. BSMax vbs bitmap 、1)

}



/// vbsビットスライスインデックスからビットマップサンプルの値の合計を返します

メソッド BSSum( vbs As%String ビットマップ As%String As%Integer

{

セット bswork = .. GetNewTMP ()、 resBSSum = .. GetNewTMP ()、 tmpBSSum = .. GetNewTMP ()

merge @ resBSSum = @ vbs @(1) do .. BMNot resBSSum )、.. BMAnd resBSSum bitmap set slice = ""

ix = 2:1: $ order (@ vbs @( "" )、-1) kill @ tmpBSSum merge @ tmpBSSum = @ vbs @( ix do .. BMAnd tmpBSSum resBSSum set $ list slice ix )= .. BMCount tmpBSSum

set val = .. CvtFromSlice スライス

kill @ resBSSum merge @ resBSSum = @ vbs @(1) do .. BMAnd resBSSum bitmap set slice = ""

ix = 2:1: $ order (@ vbs @( "" )、-1) kill @ tmpBSSum merge @ tmpBSSum = @ vbs @( ix do .. BMAnd tmpBSSum resBSSum set $ list slice ix )= .. BMCount tmpBSSum

set val = val- .. CvtFromSlice スライス

kill @ bswork 、@ resBSSum 、@ tmpBSSum quit val

}



///ビットマップとビットスライスインデックスを埋めるためのメソッド

///

///ビットマップインデックスの対応するビットを設定します

///このプロパティの指定された値

///オプションパラメータsetexist = 1を使用して、ビットを

///既存のレコードのビットマップインデックス(正しいために必要

/// BMNot())メソッドの操作

メソッド SetBitMap( idfact As%Integer プロパティ As%String As%String setexist As%String

{

set idf0 = idfact -1 \ .. # MAXBITLENGTH idf1 = idfact -1#.. #MAXBITLENGTH +1

set $ get setexist $ bit (@(.. BMGLOB )@( "EXIST" idf0 )、 idf1 )= 1

set $ bit (@(.. BMGLOB )@( "I" property value idf0 )、 idf1 )= 1

やめる

}



/// beatleysインデックスの対応するビットを設定します

///このプロパティの指定された値。

///オプションパラメータsetexist-SetBitMap()に類似

メソッド SetBitSlice( idfact As%Integer プロパティ As%String As%Integer setexist As%String

{

set idf0 = idfact -1 \ .. # MAXBITLENGTH idf1 = idfact -1#.. #MAXBITLENGTH +1

set $ get setexist $ bit (@(.. BMGLOB )@( "EXIST" idf0 )、 idf1 )= 1

set v = .. CvtToBin (+ value

ix = 1:1: $ length v set $ extract v ix $ bit (@(.. BMGLOB )@( "S" property ix idf0 )、 idf1 )= 1

やめる

}



///を含むインデックスグローバルのサブノードの名前を返します

///ビットマップインデックス(スライス= 0または未定義の場合)またはビットスライス(ghbスライス '= 0)

///このプロパティ。 プロパティが空または定義されていない場合-

///その後、既存のレコードのビットマップインデックス

メソッド GetBitMapName( プロパティ As%String スライス As%String As%String

{

quit $ get property )= "" $ name (@(.. BMGLOB )@( "EXIST" ))

quit $ name (@(.. BMGLOB )@( $ select (+ $ get slice ): "S" 、1: "I" )、 property ))

}



///デモの充填と選択

///

ClassMethod Populate( Count As%String = 10000

{

set ix = .. %New ()

ixを 設定し ます。 BMGLOB = $ name (^ BMI)

set count = $ get count 、10000)、 m = 0

セット = $ listbuild "SantaClause" "Crocodile" "Simba"

色の 設定 = $ listbuild "シアン" "マゼンタ" "イエロー" "ブラック"

if $ sortbegin (^ BMI)

idfact = 1の場合:1: カウント {

set name = $ list names 、1 + $ random $ listlength names ))))

set color = $ list colors 、1 + $ random $ listlength colors ))))

設定 = 10 + $ランダム (90)

重みの 設定 =(10+ $ランダム (40))* 100

; 色のビットマップインデックスを作成します

ixを行い ます。 SetBitMap idfact "C" color 、1)

; 重量と長さに​​ついては、ビートリーインデックスを作成します

ixを行い ます。 SetBitSlice idfact "L" length

ixを行い ます。 SetBitSlice idfact "W" weight

; テストサンプル(以下を参照)をテストするために、

; 黒と黄色のワニの総重量45〜70 cm

; 包括的に

set :(( color = "Black" )!( color = "Yellow" ))&( 長さ '<45)&( 長さ '> 70) m = m + 重量

}

if $ sortend (^ BMI)

m _ "gramms total"と 書いてください

IX 殺す

}



///テストサンプル

ClassMethod TestGetData()

{

set ix = .. %New ()

ixを 設定し ます。 BMGLOB = $ name (^ BMI)

b = .. GetNewTMP ()、 b1 = .. GetNewTMP ()を設定します

ixを行い ます。 BMEq b ix。GetBitMapName "C" )、 "Black"

ixを行い ます。 BMEq b1 ix。GetBitMapName "C" )、 "Yellow"

ixを行い ます。 BMOr b b1

ixを行い ます。 BSGeLe b1 ix。GetBitMapName "L" 、1)、45.70)

ixを行い ます。 BMAnd b b1

カウント = ixに 設定し ます BMCount b

書き込み _ 「選択されたアイテム」、!

; 選択したものの総重量を決定する

ixを 書き ます。 BSSum ix。GetBitMapName "W" 、1)、 b )_ "gramms total" ,!

do .. KillAllTMP ()

IX 殺す

}



}


添付コードには、ビットマップインデックスとクラスおよびルーチンのビットスライスを使用してデータウェアハウスを開発するための完全な関数セットが含まれており、これらの構造で必要なすべての操作をサポートします。 また、テストストレージにデータを入力するためのデモメソッドも含まれています。この方法では、グループ化関数の値(合計)が後続のテスト要求に対して直接計算されます。



##クラス User.BitMapSlice )を実行します。 人口 (1,000,000) ; 万件の記録



このテスト要求を実行するためのメソッド。同じグループ化関数の値がビットスライスを使用して計算されます。



##クラス User.BitMapSlice )を実行します。 TestGetData ()



結果とそれに費やした時間を比較できます。



短縮されたCOS構文に慣れている人のために、Cachéスタジオバージョン5.2以降では選択したコードフラグメントを完全な形式から短い形式に簡単に変換できることを思い出してください-Ctrl-Shift-Eまたはその逆-Ctrl-E

結論として、1つの微妙な点についてコメントする必要があります。 ^ CacheTempまたは^ mtempプレフィックスを使用してグローバルでフェッチするために、中間および結果のビットマップインデックスを構築することをお勧めします。 このようなグローバルはCACHETEMPデータベースに物理的に配置されており、ログに記録されないため、必要がないため、 ローカル変数を使用するよりも作業が効率的です。 この目的でローカル変数を使用することも、別の理由で望ましくありません。ユーザープロセスの16メガバイトのメモリ制限に達する可能性があります。

イタリック体の強調は、CachéDBMSの新しいバージョンには適用されません。
  1. 大規模なローカル配列
  2. 拡張メモリ
  3. 無制限のローカル配列
この記事で説明するコードは、DeepSee製品のプレゼンテーションの1つでインターシステムズから提供された情報に基づいており、その後、MacovaSoftのOrtofactデータウェアハウスで使用されました。



All Articles