Ett partiellt index är en bra idé att utesluta halva raderna i tabellen som du uppenbarligen inte behöver. Enklare:
CREATE INDEX name_idx ON table (text_col)
WHERE text_col IS NOT NULL;
Var noga med att köra ANALYZE table
efter att du har skapat indexet. (Autovacuum gör det automatiskt efter en tid om du inte gör det manuellt, men om du testar direkt efter skapandet kommer ditt test att misslyckas.)
Sedan, för att övertyga frågeplaneraren om att ett visst delindex kan användas, upprepa WHERE
villkor i frågan - även om den verkar helt överflödig:
SELECT col1,col2, .. colN
FROM table
WHERE text_col = 'my_value'
AND text_col IS NOT NULL; -- repeat condition
Voilá.
Per dokumentation:
Tänk dock på att predikatet måste matcha de villkor som används i de frågor som ska dra nytta av indexet. För att vara exakt kan ett partiellt index endast användas i en fråga om systemet kan känna igen att
WHERE
villkoret för frågan innebär matematiskt indexets predikat. PostgreSQL har inte ett sofistikerat satsbevis som kan känna igen matematiskt likvärdiga uttryck som är skrivna i olika former. (Inte bara är ett sådant generellt teorem extremt svårt att skapa, det skulle förmodligen vara för långsamt för att vara till någon verklig användning.) Systemet kan känna igen enkla olikhetsimplikationer, till exempel "x <1" innebär "x <2"; annars predikatet villkoret måste exakt matcha en del av frågansWHERE
skick eller så kommer indexet inte att kännas igen som användbart. Matchning sker vid frågeplaneringstid, inte vid körning. Som ett resultat fungerar inte parametriserade frågesatser med ett partiellt index.
När det gäller parametriserade frågor:återigen, lägg till det (redundanta) predikatet för det partiella indexet som en ytterligare konstant WHERE
skick och det fungerar bra.
En viktig uppdatering i Postgres 9.6 förbättrar till stor del chanserna för endast indexsökningar (vilket kan göra frågor billigare och frågeplaneraren kommer lättare att välja sådana frågeplaner). Relaterat:
- PostgreSQL använder inte index under count(*)