tldr:trigram kanske inte är bra på att söka efter mönster som består av ett enda tecken som upprepas N gånger (som 666666
) eftersom det bara finns ett icke-terminalt trigram och det kunde har en hög förekomst i sökutrymmet.
När gin-index används är bitmappen av rader för stor för att passa i minnet, så istället lagrar den referenser till sidor, och databasen måste utföra en ytterligare omkontroll av dessa sidor. Om antalet återkontrollerade sidor är litet är indexanvändningen fortfarande fördelaktig, men med ett stort antal omkontrollerade sidor fungerar indexet dåligt. Detta framhävs av följande rader i din förklara-utdata
Recheck Cond: (x ~~* '%666666%'::text)
Rows Removed by Index Recheck: 36257910
Heap Blocks: exact=39064 lossy=230594
Problemet är speciellt för din söksträng, dvs 666666
, med avseende på testdata.
om du kör select pg_trgm('666666')
, hittar du:
show_trgm
-------------------------
{" 6"," 66","66 ",666}
(1 row)
De första 3 trigrammen kommer inte ens att genereras i ett liknande sammanhang (korrigering föreslagen av användaren jjanes ) . Sökning på indexet ger alla sidor som innehåller 666
. Du kan validera detta genom att köra förklaringsanalysfrågan med ... ilike '%666%'
, och erhåller samma Heap Blocks
utdata enligt ovan.
om du söker med mönstret 123456
, kommer du att se att den presterar mycket bättre, eftersom den genererar en större uppsättning trigram att söka mot:
show_trgm
-------------------------------------
{" 1"," 12",123,234,345,456,"56 "}
(1 row)
På min maskin får jag följande:
|------------------------------------|
| pattern | pages rechecked |
| | exact | lossy | total |
|------------------------------------|
| 123456 | 600 | | 600 |
| 666666 | 39454 | 230592 | 270046* |
| 666 | 39454 | 230592 | 270046* |
|------------------------------------|
*this is rougly 85% of the total # of pages used for the table 't'
Här är förklarande utdata:
postgres=> explain analyze select * from t where x ~ '123456';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on t (cost=90.75..18143.92 rows=5000 width=22) (actual time=110.962..113.509 rows=518 loops=1)
Recheck Cond: (x ~ '123456'::text)
Rows Removed by Index Recheck: 83
Heap Blocks: exact=600
-> Bitmap Index Scan on t_x_idx (cost=0.00..89.50 rows=5000 width=0) (actual time=110.868..110.868 rows=601 loops=1)
Index Cond: (x ~ '123456'::text)
Planning time: 0.703 ms
Execution time: 113.564 ms
(8 rows)
postgres=> explain analyze select * from t where x ~ '666666';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on t (cost=54.75..18107.92 rows=5000 width=22) (actual time=137.143..18111.609 rows=462 loops=1)
Recheck Cond: (x ~ '666666'::text)
Rows Removed by Index Recheck: 36258389
Heap Blocks: exact=39454 lossy=230592
-> Bitmap Index Scan on t_x_idx (cost=0.00..53.50 rows=5000 width=0) (actual time=105.962..105.962 rows=593708 loops=1)
Index Cond: (x ~ '666666'::text)
Planning time: 0.420 ms
Execution time: 18111.739 ms
(8 rows)
postgres=> explain analyze select * from t where x ~ '666';
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on t (cost=54.75..18107.92 rows=5000 width=22) (actual time=102.813..17285.086 rows=593708 loops=1)
Recheck Cond: (x ~ '666'::text)
Rows Removed by Index Recheck: 35665143
Heap Blocks: exact=39454 lossy=230592
-> Bitmap Index Scan on t_x_idx (cost=0.00..53.50 rows=5000 width=0) (actual time=96.100..96.100 rows=593708 loops=1)
Index Cond: (x ~ '666'::text)
Planning time: 0.500 ms
Execution time: 17300.440 ms
(8 rows)