JetPrereadKeys() API は、読み取りをリーフ レベルの親に同期してから、目的のキー/レコードに必要なすべてのリーフ ページの非同期 IO をキューに入れます。答えは #2 だと思います。メイン テーブル レコード (バーストの長い値/LV が別のツリーに格納されていることに注意してください) が浅いか、完全にキャッシュされている場合、この JetPrereadKeys() は役に立たない可能性があります。ただし、テーブルのプライマリ ツリーが大きくて深い場合、この API は劇的に役立ちます...それは、取得するデータの形状と広がりに依存します。スペースをダンプし、ツリーの深さを見て、「データ」ページの意味を理解することで、テーブルに関するいくつかの基本を知ることができます。
esentutl /ms Your.Db /v /fName,Depth,Internal,Data
テーブルの名前、深さ、内部ページ数、およびリーフ レベル データ ページ数をリストします。テーブル名によってメイン レコード ツリーの個別の行がリストされ、その下に "[Long Values]" として LVs / がリストされます。
また、この事前読み取りキーはバースト LV にも拡張されないことに注意してください。したがって、バースト LV 列をすぐに読み取ると、残念ながら IO の後ろに固定されます。
既定のモードでは、ESE が独自のデータベース バッファー/ページ キャッシュを排他的に割り当てて制御します。JET_paramEnableFileCache は主に、終了する (または少なくとも JetTerm/JetDetach の DB) および多くの再起動を行う (通常は小さい) クライアント プロセスを対象としています。そのため、終了するたびに ESE のプライベート バッファー キャッシュが失われますが、JET_paramEnableFileCache は最近終了した場合、データがファイルキャッシュに残っている可能性があるためのパラメーター。ただし、データが ESE バッファー キャッシュと NTFS / ReFS ファイル キャッシュに二重にキャッシュされるため、大規模な DB にはお勧めできません。JET_paramEnableViewCache は以前のパラメーターを拡張し、この二重キャッシングをいくらか改善します...しかし、メモリを節約することしかできません/クリーン/変更されていないページバッファーのダブルバッファーではありません。大規模な DB の場合は、これらのパラメーターを両方とも off / false のままにします。また、これらのパラメーターを使用しない場合は、コールド パフォーマンスをテストする方が簡単です。アプリが終了した後、大きな (100 MB、おそらく 1 または 2 GB) ファイルを HD に数回コピーするだけです (HD をクリアするため)。キャッシュ)、データはコールドになります。;-)
キャッシングについて言及したので...最後に1つ-おそらく実際の問題だと思います(上記の「データの形状」でない場合)... perfmonを開いて「データベース」を見つけますおよび/または「データベース ==> インスタンス」パフォーマンス オブジェクト (これらは ESENT 用です) を確認し、キャッシュ サイズ [「データベース キャッシュ サイズ」または「データベース キャッシュ サイズ (MB)」のいずれか] を確認し、使用可能なプールの大きさを確認します。 is / ["Database Cache % Available"]... もちろん、この % を取得し、データベース キャッシュ サイズに対して計算して、アイデアを得る必要があります ... しかし、これが低い場合、これが問題になる可能性があります。 .. これは、JetPrereadKeys が既に利用可能なバッファーのみを使用するためです。そのため、健全で十分な大きさの利用可能なプールが必要です。JET_paramCacheSizeMin を大きくするか、
paramCacheSizeMin = 500
paramCacheSizeMax = 100000
paramStartFlush.. = 1000
paramStopFlushT.. = 2000
開始と停止のしきい値が、現在のキャッシュ サイズのそれぞれ 1% と 2% であることを意味します。したがって、キャッシュが 500 バッファー (最小) の場合、5 と 10 が開始/停止しきい値になります。つまり、使用可能なプールが含まれる範囲です。後で 10000 バッファーに増加した場合、使用可能なプールは 100 から 200 の範囲になります。バッファ。いずれにしても、JetPrereadKeys が必要とする可能性のあるすべてのリーフ ページに対して十分なバッファを確保できるように、これらの数値を適切な範囲にする必要があります。
このメールですべての用語を説明したわけではありません。上の記事では、B ツリーの内部ノードなどについてかなり上級者向けに説明していましたが、不明な点がある場合は、質問してください。解決します。
ありがとう、
ブレット・シャーリー [MSFT]
拡張可能ストレージ エンジンの開発者
この投稿は、無保証で「現状のまま」提供され、いかなる権利も付与しません。
PS - 最後に、JetGetThreadStats / JET_THREADSTATS で遊んでみてください。これは、API の下で行う内部操作の一部を示しています。基本的に、JET API の前後の値を読み取り、それらを差し引いて、その JET API の操作数を取得します。したがって、そこに cPagePreread が表示されます...これは、JetPrereadKeys がパフォーマンスに役立つはずの非同期 IO からディスパッチされているかどうかを確認する良い方法です。残念ながら古い OS では特定のカウンターが壊れていたことに注意してください。Win10 を使用している場合、問題はありません。それまでに確実に修正されています。;-) また、cPageRead は同期読み取りページです (これは内部ノードのために上昇する可能性があります)... これらは、さまざまな JET API のコストについて非常に有益であることがわかると思います。