sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL met pg_trgm langzamer dan volledige scan

tldr:trigrammen zijn mogelijk niet goed in het zoeken naar patronen die bestaan ​​uit een enkel teken dat N keer wordt herhaald (zoals 666666 ) omdat er maar 1 niet-terminaal trigram bestaat en dat zou komen veel voor in de zoekruimte.

Wanneer de gin-index wordt gebruikt, is de bitmap van rijen te groot om in het geheugen te passen, dus in plaats daarvan slaat het verwijzingen naar pagina's op en moet de database een nieuwe scan over deze pagina's uitvoeren. Als het aantal opnieuw gecontroleerde pagina's klein is, is het gebruik van de index nog steeds gunstig, maar met een hoog aantal opnieuw gecontroleerde pagina's presteert de index slecht. Dit wordt benadrukt door de volgende regels in uw uitleg-uitvoer

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

Het probleem is specifiek voor uw zoekreeks, d.w.z. 666666 , met betrekking tot de testgegevens.

als je select pg_trgm('666666') . uitvoert , vindt u:

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

De eerste 3 trigrammen worden niet eens gegenereerd in een ilike-context (correctie voorgesteld door gebruiker jjanes ) . Zoeken op de index levert alle pagina's op die 666 . bevatten . U kunt dit valideren door de 'explain analysis'-query uit te voeren met ... ilike '%666%' , en het verkrijgen van dezelfde Heap Blocks uitvoer zoals hierboven.

als je zoekt met het patroon 123456 , je zult zien dat het veel beter presteert, omdat het een grotere reeks trigrammen genereert om tegen te zoeken:

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

Op mijn computer krijg ik het volgende:

|------------------------------------|
| 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 is de uitvoer van de uitleg:

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)


  1. Na een PostgreSQL-herstel, krijg ik toestemming geweigerd voor relatie django_session

  2. MySQL Dubbele kolommen verwijderen op Left Join, 3 tabellen

  3. Volgende dichtstbijzijnde datum en tijd in MySQL

  4. In SQL, hoe de bovenste 2 rijen voor elke groep te selecteren?