PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

PostgreSQL menggunakan pg_trgm lebih lambat dari pemindaian penuh

tldr:trigram mungkin tidak bagus dalam mencari pola yang terdiri dari satu karakter yang diulang N kali (seperti 666666 ) karena hanya ada 1 trigram non-terminal dan bisa memiliki kemunculan yang tinggi di ruang pencarian.

Ketika indeks gin digunakan, bitmap baris terlalu besar untuk muat di memori, jadi alih-alih menyimpan referensi ke halaman, dan database harus melakukan pemindaian ulang lebih lanjut atas halaman ini. Jika jumlah halaman yang diperiksa ulang sedikit, penggunaan indeks masih menguntungkan, namun dengan jumlah halaman yang diperiksa ulang, indeks berkinerja buruk. Ini disorot oleh baris berikut dalam output penjelasan Anda

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

Masalahnya khusus untuk string pencarian Anda, yaitu 666666 , sehubungan dengan data pengujian.

jika Anda menjalankan select pg_trgm('666666') , Anda akan menemukan:

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

3 trigram pertama bahkan tidak akan dibuat dalam konteks serupa (koreksi disarankan oleh pengguna jjanes ) . Pencarian di indeks menghasilkan semua halaman yang berisi 666 . Anda dapat memvalidasi ini dengan menjalankan kueri analisis penjelasan dengan ... ilike '%666%' , dan mendapatkan Heap Blocks yang sama keluaran seperti di atas.

jika Anda mencari dengan pola 123456 , Anda akan melihat kinerjanya jauh lebih baik, karena menghasilkan kumpulan trigram yang lebih besar untuk ditelusuri:

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

Di mesin saya, saya mendapatkan yang berikut:

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

Berikut output penjelasannya:

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. Indeks dan upser unik parsial PostgreSQL

  2. postgresql - perbarui tabel pohon dengan baris dari tabel yang sama dengan mengubah id dan parent_id

  3. Bisakah saya menggunakan PENGECUALIAN dalam FOR LOOP untuk memaksa kelanjutan pada kesalahan?

  4. Mengapa NULL tidak dapat dikonversi ke null JSON di postgreSQL?

  5. Alat Hibernasi gagal mendapatkan info indeks dari tabel Postgres