PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Postgres Materialized Path - Quali sono i vantaggi dell'utilizzo di ltree?

TL;DR Non è possibile ottenere etichette riutilizzabili, modelli di ricerca complessi e ricerche di ascendenza su più nodi discendenti (o un singolo nodo il cui percorso non è stato recuperato) utilizzando un indice di percorso materializzato.

Per chi fosse interessato ai dettagli cruenti...

In primo luogo, la tua domanda è rilevante solo se non stai riutilizzando alcuna etichetta nella descrizione del tuo nodo. Se lo fossi, l'l-tree è davvero l'unica opzione dei due. Ma le implementazioni del percorso materializzato in genere non ne hanno bisogno, quindi mettiamolo da parte.

Un'ovvia differenza sarà nella flessibilità nei tipi di ricerche che ti offre l-tree. Considera questi esempi (da ltree documenti collegati nella tua domanda):

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

La prima query è ovviamente realizzabile con percorso materializzato. L'ultimo è anche realizzabile, in cui regoleresti la query come ricerca di pari livello. Il caso centrale, tuttavia, non è direttamente realizzabile con una singola ricerca nell'indice. Dovresti dividerlo in due query (tutti i discendenti + tutti gli antenati) o ricorrere a una scansione della tabella.

E poi ci sono query davvero complesse come questa (anche dai documenti):

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

Un indice di percorso materializzato sarebbe inutile qui e sarebbe necessaria una scansione completa della tabella per gestirlo. l-tree è l'unica opzione se desideri eseguire questa operazione come query SARGable.

Ma per le operazioni gerarchiche standard, trovare uno qualsiasi di:

  • genitore
  • bambini
  • discendenti
  • nodi radice
  • nodi foglia

il percorso materializzato funzionerà altrettanto bene di l-tree. Contrariamente all'articolo collegato sopra , la ricerca di tutti i discendenti di un antenato comune è molto fattibile usando un b-tree. Il formato della query WHERE path LIKE 'A.%' è SARGable a condizione che il tuo indice sia preparato correttamente (ho dovuto contrassegnare esplicitamente il mio indice di percorso con varchar_pattern_ops per farlo funzionare).

Ciò che manca in questo elenco è trovare tutti gli antenati per un discendente. Il formato della query WHERE 'A.B.C.D' LIKE path || '.%' purtroppo non utilizzerà l'indice. Una soluzione alternativa implementata da alcune librerie è analizzare i nodi predecessori dal percorso e interrogarli direttamente:WHERE id IN ('A', 'B', 'C') . Tuttavia, questo funzionerà solo se stai prendendo di mira gli antenati di un nodo specifico di cui hai già recuperato il percorso. l-tree vincerà su questo.