0
vit=# select count(*) from evtags;
count
---------
4496914
vit=# explain select tag from evtags where evid in (1002, 1023);
QUERY PLAN
---------------------------------------------------------------------------------
Index Only Scan using evtags_pkey on evtags (cost=0.00..15.64 rows=12 width=7)
Index Cond: (evid = ANY ('{1002,1023}'::integer[]))
到目前为止,这看起来完全没问题。接下来,我想使用另一个表中的ID而不是在查询中指定它们。选择包含在另一个表中的ID的记录
vit=# select count(*) from zzz;
count
-------
49738
在这里,我们去...
vit=# explain select tag from evtags where evid in (select evid from zzz);
QUERY PLAN
-----------------------------------------------------------------------
Hash Semi Join (cost=1535.11..142452.47 rows=291712 width=7)
Hash Cond: (evtags.evid = zzz.evid)
-> Seq Scan on evtags (cost=0.00..69283.14 rows=4496914 width=11)
-> Hash (cost=718.38..718.38 rows=49738 width=4)
-> Seq Scan on zzz (cost=0.00..718.38 rows=49738 width=4)
为什么在更多更大的表索引扫描,什么是应该做的正确方法?
编辑
我重新创建我的zzz
表,现在它是由于某种原因,更好:
vit=# explain analyze select tag from evtags where evid in (select evid from zzz);
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=708.00..2699.17 rows=2248457 width=7) (actual time=28.935..805.923 rows=244353 loops=1)
-> HashAggregate (cost=708.00..710.00 rows=200 width=4) (actual time=28.893..54.461 rows=38822 loops=1)
-> Seq Scan on zzz (cost=0.00..601.80 rows=42480 width=4) (actual time=0.032..10.985 rows=40000 loops=1)
-> Index Only Scan using evtags_pkey on evtags (cost=0.00..9.89 rows=6 width=11) (actual time=0.015..0.017 rows=6 loops=38822)
Index Cond: (evid = zzz.evid)
Heap Fetches: 0
Total runtime: 825.651 ms
但几经执行它改变
vit=# explain analyze select tag from evtags where evid in (select evid from zzz);
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------
Merge Semi Join (cost=4184.11..127258.48 rows=235512 width=7) (actual time=38.269..1461.755 rows=244353 loops=1)
Merge Cond: (evtags.evid = zzz.evid)
-> Index Only Scan using evtags_pkey on evtags (cost=0.00..136736.89 rows=4496914 width=11) (actual time=0.038..899.647 rows=3630070 loops=1)
Heap Fetches: 0
-> Materialize (cost=4184.04..4384.04 rows=40000 width=4) (actual time=38.212..61.038 rows=40000 loops=1)
-> Sort (cost=4184.04..4284.04 rows=40000 width=4) (actual time=38.208..51.104 rows=40000 loops=1)
Sort Key: zzz.evid
Sort Method: external sort Disk: 552kB
-> Seq Scan on zzz (cost=0.00..577.00 rows=40000 width=4) (actual time=0.018..8.833 rows=40000 loops=1)
Total runtime: 1484.293 ms
...这实际上是较慢的。有什么方法可以暗示它是一个“正确的”执行计划吗?
这些操作的要点是,我想对我的数据的一个子集执行大量查询,并希望使用单独的临时表来保存要处理的记录的ID。
做你的表有主/外键(没有索引扫描,可能有两个)你有有效的统计数据吗?请添加表格定义,包括PK/FK和/或索引。顺便说一句:如果结果集很小并且大部分元组都是需要的,这种计划是正常的。 BTW2:'解析分析'会显示*估计和测量的计数/数字。 – wildplasser 2013-04-30 09:46:39
更新了我的问题。 – mifki 2013-04-30 10:11:15
您是否重新创建'zzz'表后运行'vacuum analyze'? (它会更新统计信息)另外:“外”表需要大约50%的行,索引可能无助于找到它们(因为基本上每个磁盘页面都将被需要)。你可以尝试将random_page_cost降低到1.5(或work_mem为更小的值)来强制执行索引扫描,但只有当需要获取更少的行/页时才有意义。 BTW:zzz表有PK/FK /索引吗? **请添加表格定义**,包括PK/FK /索引。 – wildplasser 2013-04-30 10:25:19