sql >> Database >  >> RDS >> PostgreSQL

Postgres gematerialiseerd pad - Wat zijn de voordelen van het gebruik van ltree?

TL;DR Herbruikbare labels, complexe zoekpatronen en zoekopdrachten naar voorouders op meerdere onderliggende knooppunten (of een enkel knooppunt waarvan het pad nog niet is opgehaald) kunnen niet worden bereikt met behulp van een gematerialiseerde padindex.

Voor degenen die geïnteresseerd zijn in de bloederige details...

Ten eerste is uw vraag alleen relevant als u geen labels in uw knooppuntbeschrijving hergebruikt. Als dat zo was, is de l-tree echt de enige optie van de twee. Maar implementaties van gematerialiseerde paden hebben dit meestal niet nodig, dus laten we dat terzijde schuiven.

Een duidelijk verschil zit in de flexibiliteit in de soorten zoekopdrachten die l-tree u geeft. Overweeg deze voorbeelden (uit de ltree documenten gelinkt in uw vraag):

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

De eerste query is duidelijk haalbaar met een gematerialiseerd pad. De laatste is ook haalbaar, waarbij u de zoekopdracht zou aanpassen als een zoekopdracht voor een broer of zus. Het middelste geval is echter niet direct bereikbaar met een enkele index-lookup. U moet dit ofwel opsplitsen in twee zoekopdrachten (alle afstammelingen + alle voorouders), of uw toevlucht nemen tot een tabelscan.

En dan zijn er echt complexe vragen zoals deze (ook uit de documenten):

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

Een gematerialiseerde padindex zou hier nutteloos zijn en een volledige tabelscan zou nodig zijn om dit te verwerken. l-tree is de enige optie als je dit als een SARGable query wilt uitvoeren.

Maar voor de standaard hiërarchische bewerkingen, het vinden van een van:

  • ouder
  • kinderen
  • afstammelingen
  • hoofdknooppunten
  • bladknopen

gematerialiseerd pad zal net zo goed werken als l-tree. In tegenstelling tot het artikel waarnaar hierboven is gelinkt , zoeken naar alle afstammelingen van een gemeenschappelijke voorouder is heel goed te doen met behulp van een b-tree. De query-indeling WHERE path LIKE 'A.%' is SARGable op voorwaarde dat uw index correct is voorbereid (ik moest mijn padindex expliciet taggen met varchar_pattern_ops om dit te laten werken).

Wat ontbreekt in deze lijst is het vinden van alle voorouders voor een nakomeling. Het zoekformaat WHERE 'A.B.C.D' LIKE path || '.%' gaat de index helaas niet gebruiken. Een tijdelijke oplossing die sommige bibliotheken implementeren, is om de voorouderknooppunten uit het pad te ontleden en ze rechtstreeks op te vragen:WHERE id IN ('A', 'B', 'C') . Dit werkt echter alleen als u zich richt op voorouders van een specifiek knooppunt waarvan u het pad al hebt opgehaald. l-tree gaat winnen.




  1. Haal het weeknummer van een datum in PostgreSQL

  2. Converteer datetime-waarde naar tekenreeks

  3. Alternatief voor django.db.close_connection()

  4. Mysql krijgt de laatste id van een specifieke tabel