4

私は2つの質問について考えてきました。これに関するインターネット上のリソースは見つかりませんでした。dbms はどのように処理しますか? それとも彼らは?特にオラクル。

質問の前に、例を示します。マスター テーブル「MASTER」とスレーブ テーブル「SLAVE」があるとします。マスターテーブルには、主キーである「ID」列があり、インデックスはOracleによって作成されます。スレーブテーブルには、マスターテーブルを参照する外部キー「MASTER_ID」と「SLAVE_NO」があります。これら 2 つの組み合わせがスレーブ テーブルの主キーであり、再びインデックスが作成されます。

 **MASTER**  |  **SLAVE**
     (P) ID <------> (P)(F) MASTER_ID 
                     (P) SLAVE_NO

さて、質問です。

1- MASTER_ID が自動インクリメント列であり、レコードが削除されていない場合、テーブルのインデックスが不均衡になりませんか? Oracle は定期的にインデックスを再構築しますか? 私の知る限り、Oracle はビルド時にのみインデックス ブランチのバランスを取ります。Oracle はインデックスを自動的に再構築しますか? レベルがいくつかの高レベルに上がるとしますか?

2-Oracleが自動的に再構築しないと仮定すると、インデックスを定期的に再構築するジョブをスケジュールすることを除いて、SLAVEテーブルの主キー列を逆に注文する方が賢明でしょうか? つまり、「MASTER_ID」、「SLAVE_NO」を「SLAVE_NO」、「MASTER_ID」と並べ替えるのではなく、スレーブ テーブルの B ツリー インデックスをよりバランスの取れたものにするのに役立ちますか? (まあ、各マスターテーブルには正確な数のスレーブレコードがないかもしれませんが、それでも逆順よりは良いようです)

それについて何か知っている人はいますか?それとも意見?

4

2 に答える 2

7

が自動インクリメントされた列で、レコードが削除されていない場合MASTER_ID、テーブルのインデックスが不均衡になりませんか?

Oracleのインデックスは「不均衡」になることはありません。インデックス内のすべての葉は、他の葉と同じ深さです。

ページ分割自体が新しいレベルを導入することはありません。リーフ ページは、非自己均衡ツリーの場合のように、新しいページの親にはなりません。

代わりに、分割ページの兄弟が作成され、新しいレコード (さらに古いページのレコードの一部) が新しいページに移動します。新しいページへのポインターが親に追加されます。

親ページもスペースが不足している場合 (新しく作成されたリーフ ページへのポインターを受け入れることができない場合)、同様に分割されます。

これらの分割は、ルート ページまで伝播する可能性があります。ルート ページの分割は、インデックスの深さを増加させる唯一のものです (すべてのページに対して一度に行います)。

インデックス ページはさらに、各リストが独自のレベルにある二重リンク リストに編成されます。木のバランスが悪いと、これは不可能です。

master_idが自動インクリメントされる場合、これはすべての分割が最後に発生することを意味し (分割と呼ばれ90/10ます)、可能な限り高密度のインデックスを作成します。

SLAVEテーブルの主キー列を逆順に並べた方が賢明でしょうか?

いいえ、上記の理由からそうではありません。

に頻繁に参加slaveする場合は、 でインデックス付けされた 2 つのテーブルのうちのmasterを作成することを検討してください。これは、同じ を共有する両方のテーブルのレコードが同じまたは近くのデータ ページに移動することを意味し、それらの間の結合が非常に高速になります。CLUSTERmaster_idmaster_id

エンジンがmasterインデックスなどを使用して からレコードを見つけた場合、これは、slaveその と結合するからのレコードを既に見つけたことも意味しmasterます。逆に、 aを見つけることはslave、その を見つけることも意味しmasterます。

于 2012-06-05T17:18:51.990 に答える
4

の b ツリー インデックスMASTER_IDは、「バランス」の最も有用な定義に対してバランスが保たれます。特に、ルート ブロックとすべての子ブロックの間の距離は常に同じになり、すべてのブランチのデータ量は、他の兄弟ブランチのデータ量と少なくともほぼ等しくなります。

シーケンス生成列のインデックスにデータを挿入すると、特定のレベルのデータ量が増加すると、Oracle はリーフで 90 対 10 のブロック分割を実行します。たとえば、10 行を保持できるリーフ ブロックがあり、それがいっぱいで 11 行目を追加したい場合、Oracle は新しいブロックを作成し、最初のブロックに最初の 9 エントリを残し、2 つのエントリを最初のブロックに置きます。新しいブロックのアドレスで親ブロックを更新します。あまりにも多くの子のアドレスを保持しているために親ブロックを分割する必要がある場合、同様のプロセスが発生します。これにより、インデックスは生涯を通じて比較的バランスが取れたままになります。Richard Foote (Oracle インデックスの専門家) は、 When Does an Oracle Index Increase in Heightに関する優れたブログを公開しており、これがどのように機能するかについてさらに詳しく説明しています。

インデックスが歪むことを潜在的に心配する必要がある唯一のケースは、インデックスの左側からすべてではなくほとんどのブロックを定期的に削除する場合です。たとえば、インデックスの左側からデータの 90% を削除して、データを指すすべてのリーフ ノードに 1 つの行を残すことにした場合、一部のパスが非常に多くのデータにつながるという意味で、インデックスが不均衡になる可能性があります。他のパスより。Oracle は、完全に空になるまでインデックス リーフ ノードを再利用しないため、実際に必要なスペースよりも多くのスペースを使用して、インデックスの左側で終了する可能性があります。これは実際にはシステムのパフォーマンスに大きな影響を与えるものではありません。これはスペースの使用率の問題ですが、データをパージした後にインデックスを結合する (またはパージを構成して

于 2012-06-05T17:29:04.833 に答える