PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL mit pg_trgm ist langsamer als der vollständige Scan

tldr:Trigramme sind möglicherweise nicht gut bei der Suche nach Mustern, die aus einem einzelnen Zeichen bestehen, das N-mal wiederholt wird (z. B. 666666 ), weil es nur 1 nicht-terminales Trigramm gibt und das könnte haben ein hohes Vorkommen im Suchraum.

Wenn der Gin-Index verwendet wird, ist die Bitmap der Zeilen zu groß, um in den Speicher zu passen, also speichert sie stattdessen Verweise auf Seiten, und die Datenbank muss einen weiteren Recheck-Scan über diese Seiten durchführen. Wenn die Anzahl der nachgeprüften Seiten klein ist, ist die Index-Nutzung immer noch vorteilhaft, aber bei einer hohen Anzahl nachgeprüfter Seiten schneidet der Index schlecht ab. Dies wird durch die folgenden Zeilen in Ihrer EXPLAIN-Ausgabe hervorgehoben

   Recheck Cond: (x ~~* '%666666%'::text)
   Rows Removed by Index Recheck: 36257910
   Heap Blocks: exact=39064 lossy=230594

Das Problem betrifft speziell Ihre Suchzeichenfolge, d. h. 666666 , in Bezug auf die Testdaten.

wenn Sie select pg_trgm('666666') ausführen , finden Sie:

        show_trgm        
-------------------------
 {"  6"," 66","66 ",666}
(1 row)

Die ersten 3 Trigramme werden nicht einmal in einem ähnlichen Kontext generiert (Korrektur vorgeschlagen von Benutzer jjanes ) . Die Suche im Index ergibt alle Seiten, die 666 enthalten . Sie können dies überprüfen, indem Sie die EXPLAIN-Analyse-Abfrage mit ... ilike '%666%' ausführen , und dieselben Heap Blocks erhalten Ausgabe wie oben.

wenn Sie mit dem Muster 123456 suchen , werden Sie sehen, dass es eine viel bessere Leistung erbringt, da es eine größere Menge von Trigrammen für die Suche generiert:

              show_trgm              
-------------------------------------
 {"  1"," 12",123,234,345,456,"56 "}
(1 row)

Auf meinem Rechner erhalte ich Folgendes:

|------------------------------------|
| 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'

Hier ist die EXPLAIN-Ausgabe:

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)