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がこれで勝ちます。