2016-05-10 52 views
0

我执行一个SQL查询与两个几乎相同的子查询像这样的一个路由数据库上,周围18mio条目:二几乎相同的子查询需要更长的时间

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,而第二个子查询需要0.02ms!有时候是相反的,所以第二个查询是慢的。当我将查询作为单个查询运行时,它们会在10ms内返回。所以我假设没有足够的缓冲区内存来执行这两个查询,但是我已经增加了大部分默认值。

我目前的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

不知道为什么你有不同的时间。我的猜测是第一次扫描表,第二次利用一些缓存,所以花费更少的时间。

尝试反转querys的顺序,看看你是否有类似的结果,或时间的变化

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 

BTW:你应该创建一个target指数和source一个索引。正如你可以在EXPLAIN看到查询perfoming一个SEQ SCAN

编辑:看后EXPLAIN消息Rows Removed by Filter: 17052688 VS Rows Removed by Filter: 94也许target更快地出现在搜索和limit 1停止搜索决策看起来是更快。尝试使用不同的ID值这是您创建一个索引的另一个原因。

+0

创建索引完成了这项工作。起初我很想知道,因为我认为我已经创建了它们,但是表格在内部使用不同的具有索引的源和目标的id,但是没有osm id的索引。 – ltsstar

+0

是的,索引应该是'osm_source_id'和'osm_target_id'我的坏 –

相关问题