PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

PostgreSQL używający pg_trgm wolniej niż pełne skanowanie

tldr:trygramy mogą nie być dobre w wyszukiwaniu wzorców składających się z pojedynczego znaku powtórzonego N razy (takich jak 666666 ), ponieważ istnieje tylko jeden trygram nieterminalny, który może mają wysokie występowanie w przestrzeni wyszukiwania.

Kiedy używany jest indeks gin, bitmapa wierszy jest zbyt duża, aby zmieścić się w pamięci, więc zamiast tego przechowuje odniesienia do stron, a baza danych musi wykonać dalsze ponowne sprawdzenie skanowania tych stron. Jeśli liczba ponownie sprawdzonych stron jest niewielka, wykorzystanie indeksu jest nadal korzystne, jednak przy dużej liczbie ponownie sprawdzanych stron indeks działa słabo. Jest to podkreślone przez następujące wiersze w wyniku wyjaśnienia

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

Problem dotyczy konkretnego ciągu wyszukiwania, tj. 666666 , w odniesieniu do danych testowych.

jeśli uruchomisz select pg_trgm('666666') , znajdziesz:

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

Pierwsze 3 trygramy nie zostaną nawet wygenerowane w podobnym kontekście (poprawka sugerowana przez użytkownika jjanes ) . Wyszukiwanie w indeksie daje wszystkie strony zawierające 666 . Możesz to sprawdzić, uruchamiając zapytanie analizy wyjaśniania za pomocą ... ilike '%666%' i uzyskanie tych samych Heap Blocks wyjście jak wyżej.

jeśli szukasz według wzorca 123456 , zobaczysz, że działa znacznie lepiej, ponieważ generuje większy zestaw trygramów do wyszukiwania:

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

Na moim komputerze otrzymuję następujące informacje:

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

Oto wynik wyjaśnienia:

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Atomikos:dane nie są zapisywane podczas korzystania z PostgreSQL

  2. Jak dopasować cały dzień do pola daty i godziny?

  3. Błąd podczas używania R do pobierania danych uwierzytelniających z Windows Cred Vault

  4. Dostrajanie operacji wejścia/wyjścia (I/O) dla PostgreSQL

  5. Tworzenie częściowego unikalnego indeksu za pomocą sqlalchemy na Postgres