sql >> データベース >  >> RDS >> PostgreSQL

pg_trgmを使用するPostgreSQLは、フルスキャンよりも低速です

    tldr:トリグラムは、N回繰り返される単一の文字で構成されるパターンの検索に適していない場合があります(666666など)。 )非終端記号が1つしか存在せず、可能性がある サーチスペースでの発生率が高い。

    gin-indexを使用すると、行のビットマップが大きすぎてメモリに収まらないため、代わりにページへの参照が格納され、データベースはこれらのページに対してさらに再チェックスキャンを実行する必要があります。再チェックされたページの数が少ない場合でも、インデックスの使用は有益ですが、再チェックされたページの数が多いと、インデックスのパフォーマンスが低下します。これは、Explain出力の次の行で強調表示されています

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

    この問題は検索文字列に固有です。つまり、666666 、テストデータに関して。

    select pg_trgm('666666')を実行する場合 、次のようになります:

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

    最初の3つのトリグラムはilikeコンテキストでは生成されません(ユーザーjjanes<によって修正が提案されました/ a> ) 。インデックスを検索すると、666を含むすべてのページが表示されます 。これを検証するには、... ilike '%666%'を使用してexplainanalyzeクエリを実行します。 、同じHeap Blocksを取得します 上記のように出力します。

    パターン123456で検索する場合 、検索対象のトリグラムのセットが大きくなるため、パフォーマンスが大幅に向上します。

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

    私のマシンでは、次のようになります。

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

    説明の出力は次のとおりです。

    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. 複数のパラメータを持つ文字列を受け入れるMySQLストアドプロシージャ

    2. PHPを使用してMySQLデータベースに保存するIPアドレス

    3. WHERE IN(IDの配列)

    4. nullの数が少ないものからnullがないものまでの列を使用して行を並べ替えます