sql >> データベース >  >> RDS >> PostgreSQL

Postgresマテリアライズドパス-ltreeを使用する利点は何ですか?

    TL; DR 再利用可能なラベル、複雑な検索パターン、および複数の子孫ノード(またはパスがまだ取得されていない単一のノード)に対する祖先検索は、マテリアライズドパスインデックスを使用して実行することはできません。

    残酷な詳細に興味のある人のために...

    まず、質問は、ノードの説明でラベルを再利用していない場合にのみ関係します。もしそうなら、lツリーは実際には2つの唯一のオプションです。ただし、マテリアライズドパスの実装では通常これは必要ないため、脇に置いておきましょう。

    明らかな違いの1つは、l-treeが提供する検索の種類の柔軟性にあります。これらの例を検討してください(ltreeから) 質問にリンクされているドキュメント):

    foo         Match the exact label path foo
    *.foo.*     Match any label path containing the label foo
    *.foo       Match any label path whose last label is foo
    

    最初のクエリは、マテリアライズされたパスで明らかに達成可能です。最後のものも達成可能であり、兄弟ルックアップとしてクエリを調整します。ただし、真ん中のケースは、単一のインデックスルックアップでは直接達成できません。これを2つのクエリ(すべての子孫+すべての祖先)に分割するか、テーブルスキャンに頼る必要があります。

    そして、このような本当に複雑なクエリがあります(これもドキュメントから):

    Top.*{0,2}.sport*@.!football|tennis.Russ*|Spain
    

    マテリアライズドパスインデックスはここでは役に立たず、これを処理するには全表スキャンが必要になります。これをSARGableクエリとして実行する場合は、l-treeが唯一のオプションです。

    ただし、標準の階層操作の場合、次のいずれかを検索します。

    • 子供
    • 子孫
    • ルートノード
    • リーフノード

    マテリアライズされたパスは、l-treeと同様に機能します。 上記のリンク先の記事> 、共通の祖先のすべての子孫を検索することは、bツリーを使用して非常に実行可能です。クエリ形式WHERE path LIKE 'A.%' インデックスが適切に準備されていれば、SARGableです(パスインデックスにvarchar_pattern_opsを明示的にタグ付けする必要がありました これを機能させるために)。

    このリストに欠けているのは、すべての祖先を見つけることです。 子孫のために。クエリ形式WHERE 'A.B.C.D' LIKE path || '.%' 残念ながら、インデックスは使用しません。一部のライブラリが実装する回避策の1つは、パスから祖先ノードを解析し、それらを直接クエリすることです。WHERE id IN ('A', 'B', 'C') 。ただし、これは、パスを既に取得している特定のノードの祖先をターゲットにしている場合にのみ機能します。 l-treeがこれで勝ちます。




    1. SQLServerで廃止される4つのデータ型

    2. PostgreSQL配列に値が含まれているかどうかを確認する方法

    3. Cの紹介

    4. テーブルの重複を削除する