4

階層データをinnoDBテーブルに保存する方法がわかりません。

parent_id各行にを格納する方法の欠点についてたくさん読んだことがあります。しかし今問題は、私が非常に大きなデータベース(約5000万行)を持っていることです。階層はほとんど深くありません(3〜6レベル)。

多くのウェブサイトは、「入れ子集合モデル」をparent-id-storing-methodのより良い代替手段として採用することを推奨しています。ただし、Webサイトのユーザーによって常に変更(など)が行われUPDATEINSERTテーブルのサイズが原因で、これには時間がかかりすぎます(「入れ子集合モデル」の変更はパフォーマンスが非常に低いため)。

updateだから私の質問は:多くの/insertコマンドでどのように効率的に大きな階層データを保存するのですか?(また、テーブル全体をブロックすることはオプションではありません[-> innoDB-table])

4

2 に答える 2

2

ツリーを頻繁に更新する必要がある場合、ネストされたセットの設計は間違いなく困難です。ツリーの大部分の番号を付け直す必要があります。

これを軽減するための1つの提案は、整数の代わりに浮動小数点数を使用することです。ツリーに新しいノードを挿入すると、新しいノードの親のネストされたセット番号の間にいくつかのFLOAT番号を見つけるのは比較的簡単です。最終的には浮動小数点数の精度の限界に達する可能性がありますが、ツリーはそれほど深くないため、長い間発生することはありません。

私が書いたもう1つのテクニックは、クロージャーテーブルと呼ばれます。階層を格納するこの方法により、ツリーの多くを更新しなくても、大きなツリーにノードを挿入/更新/削除することがはるかに簡単になります。また、単一の非再帰SQLクエリでツリー全体または任意のサブツリーをクエリできます。

クロージャーテーブルの詳細については、以下を参照してください。


コメントを再確認してください。

隣接リストは単純で、冗長性が最小限であり、入れ子集合ではサポートされていないFK関係をサポートします。再帰クエリを使用する場合、隣接リストは任意の深さのツリー全体のクエリをサポートします。ただし、MySQLは再帰クエリをサポートしていません。

直接の親子関係(つまり、1レベルの深さ)のみをクエリする必要がある場合、または固定の深さのツリーのみをクエリする必要がある場合は、隣接リストで問題ありません。

于 2013-01-01T21:52:24.933 に答える
1

階層データの場合、階層を分離しておくのが好きです。たとえば、従業員の階層を扱っている場合、私は通常、次のようなことを行います-

create table employee (
    id serial primary key,
    name varchar(50));

create table roster (
    id serial primary key,
    employee_id int references employee (id),
    supervisor_id int references employee (id));

これを拡張して、テーブルにrow_dateまたはフィールドをstart_date追加することにより、履歴階層を提供できます。stop_dateroster

uniqueビジネスルールを適用するために、該当する場合は制約とトリガーが適用されていることを確認してください。

于 2013-01-01T21:50:37.777 に答える