sql >> Database >  >> RDS >> PostgreSQL

unaccent() voorkomt indexgebruik in Postgres

onveranderlijke variant van unaccent()

Ter verduidelijking van de verkeerde informatie in het momenteel geaccepteerd, onjuist antwoord :
Expressie-indexen staan ​​alleen IMMUTABLE toe functies (om voor de hand liggende redenen) en unaccent() is alleen STABLE . De oplossing die je in de opmerking hebt voorgesteld is ook problematisch. Gedetailleerde uitleg en een juiste oplossing daarvoor :

Afhankelijk van de inhoud van tags->name het kan handig zijn om unaccent() . toe te voegen naar de uitdrukkingsindex, maar dat staat haaks op de vraag waarom de index niet werd gebruikt:

Eigenlijk probleem / oplossing

De operator LIKE in uw zoekopdracht is subtiel fout (meest waarschijnlijke). Je doet niet als je 'Weststrasse' wilt interpreteren als zoekpatroon, wil je de (genormaliseerde) string as is matchen. Vervang door de = operator, en u ziet een (bitmap) indexscan met uw huidige index, ongeacht van de functie volatiliteit van unaccent() :

SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))

Waarom?

De juiste operand van LIKE is een patroon . Postgres kan geen gewone btree-index gebruiken voor patroonovereenkomst ( uitzonderingen zijn van toepassing ). Een LIKE met een gewone string als patroon (geen speciale tekens) kan worden geoptimaliseerd met een gelijkheidscontrole op de btree-index. Maar als er speciale tekens in de tekenreeks staan, dit index is uit.

Als er een IMMUTABLE . is functie rechts van LIKE , het kan onmiddellijk worden geëvalueerd en de genoemde optimalisatie is nog steeds mogelijk. Per documentatie over Functievolatiliteitscategorieën :

Hetzelfde is niet mogelijk met een lagere functievolatiliteit (STABLE of VOLATILE ). Dat is de reden waarom uw "oplossing" van het faken van een IMMUTABLE unaccent() leek te werken, maar het is echt lippenstift op een varken aanbrengen.

Om te herhalen:

  • Als je wilt werken met LIKE en patronen, gebruik een trigram index .
  • Als je niet wilt werken met LIKE en patronen, gebruik de equality operator =



  1. Maak een functie om de huidige datum en tijd in orakel terug te geven

  2. Inloggen mislukt voor gebruiker 'NT AUTHORITY\NETWORK SERVICE'

  3. MariaDB JSON_VALUE() versus JSON_QUERY():wat is het verschil?

  4. stuur gegevens naar MySQL met AJAX + jQuery + PHP