2016-05-10 2 views
0

を取ります第二ほぼ同じサブクエリは、私の周り18mioエントリを持つルーティングデータベース上でこのような2つのほぼ同じサブクエリでSQLクエリを実行し、はるかに長い

EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT source.source, target.target FROM 
    (SELECT source FROM at_2po_4pgr WHERE osm_source_id=380253639 LIMIT 1) as source, 
    (SELECT target FROM at_2po_4pgr WHERE osm_target_id=373850046 LIMIT 1) as target 

以下の解析リターンを説明:

Nested Loop (cost=0.00..491634.63 rows=1 width=8) (actual time=6437.767..6437.768 rows=1 loops=1) 
    Output: at_2po_4pgr.source, at_2po_4pgr_1.target 
    Buffers: shared hit=6136 read=1684402 
    -> Limit (cost=0.00..215090.14 rows=1 width=4) (actual time=6437.740..6437.740 rows=1 loops=1) 
     Output: at_2po_4pgr.source 
     Buffers: shared hit=6132 read=1684402 
     -> Seq Scan on public.at_2po_4pgr (cost=0.00..1935811.25 rows=9 width=4) (actual time=6437.738..6437.738 rows=1 loops=1) 
       Output: at_2po_4pgr.source 
       Filter: (at_2po_4pgr.osm_source_id = 380253639) 
       Rows Removed by Filter: 17052688 
       Buffers: shared hit=6132 read=1684402 
    -> Limit (cost=0.00..276544.46 rows=1 width=4) (actual time=0.020..0.020 rows=1 loops=1) 
     Output: at_2po_4pgr_1.target 
     Buffers: shared hit=4 
     -> Seq Scan on public.at_2po_4pgr at_2po_4pgr_1 (cost=0.00..1935811.25 rows=7 width=4) (actual time=0.020..0.020 rows=1 loops=1) 
       Output: at_2po_4pgr_1.target 
       Filter: (at_2po_4pgr_1.osm_target_id = 373850046) 
       Rows Removed by Filter: 94 
       Buffers: shared hit=4 
Planning time: 0.109 ms 
Execution time: 6437.887 ms 

この場合、最初のサブクエリは約6500ms必要ですが、2番目のサブクエリは0.02msだけ必要です!時にはそれは別の方法ですので、2番目のクエリは遅いです。 1つのクエリとしてクエリを実行すると、10ミリ秒以内に戻ります。だから両方のクエリを実行するのに十分なバッファメモリが用意されていないと仮定しますが、既定値の大部分をすでに多く増やしています。

私の現在のPostgreSQLのメモリ設定は以下のとおりです。

# - Memory - 

shared_buffers = 12GB     # min 128kB 
             # (change requires restart) 
#huge_pages = try      # on, off, or try 
             # (change requires restart) 
temp_buffers = 64MB      # min 800kB 
#max_prepared_transactions = 0   # zero disables the feature 
             # (change requires restart) 
# Note: Increasing max_prepared_transactions costs ~600 bytes of shared memory 
# per transaction slot, plus lock space (see max_locks_per_transaction). 
# It is not advisable to set max_prepared_transactions nonzero unless you 
# actively intend to use prepared transactions. 
work_mem = 256MB        # min 64kB 
maintenance_work_mem = 512MB   # min 1MB 
#autovacuum_work_mem = -1    # min 1MB, or -1 to use maintenance_work_mem 
#max_stack_depth = 2MB     # min 100kB 
dynamic_shared_memory_type = posix  # the default is the first option 
             # supported by the operating system: 
             # posix 
             # sysv 
             # windows 
             # mmap 
             # use none to disable dynamic shared memory 

だから私は、これらの異なる実行時間の理由のために絶対に見当もつかない。

+0

選択制限1は「条件xyzを満たす最初の行を取得してください」とは異なりますが、すべてを削除した後に条件を満たすすべての行を取得する通常のクエリ - 1 – Leo

答えて

1

なぜあなたの時間が異なるのか分かりません。私の推測では、最初にテーブルをスキャンし、2番目のキャッシュではキャッシュを利用するので時間がかかりません。

はquerysの順序を逆にしてみて、あなたが同様の結果を持っているかどうか、時間がBTW

EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT source.source, target.target FROM   
    (SELECT target FROM at_2po_4pgr WHERE osm_target_id=373850046 LIMIT 1) as target, 
    (SELECT source FROM at_2po_4pgr WHERE osm_source_id=380253639 LIMIT 1) as source 

変更:あなたはtargetための一つの指標とsourceに1つのインデックスを作成する必要があります。あなたは、クエリがSEQ SCAN

EDITをperfomingさEXPLAIN上で見ることができるように:Rows Removed by Filter: 94対EXPLAINメッセージRows Removed by Filter: 17052688を見た後、多分targetは高速であるように、検索づくりに見える停止limit 1検索に早く現れると。異なるID値で試してください。これは、1つのインデックスを作成するもう一つの理由です。

+0

インデックスが仕事をしました。まず、私がすでに作成していると仮定していたので、最初は疑問に思っていましたが、テーブルはソースとターゲットに異なるIDを内部的に使用していましたが、インデックスはありませんでした。 – ltsstar

+0

はい、インデックスは 'osm_source_id'と' osm_target_id'のためになければなりません –

関連する問題