Sql 简单情况下的子查询性能
Postgresql 10-Ubuntu LTS最新版本-1CPU 2GB Ram-未安装其他软件Sql 简单情况下的子查询性能,sql,postgresql,Sql,Postgresql,Postgresql 10-Ubuntu LTS最新版本-1CPU 2GB Ram-未安装其他软件 两个表,都有索引: 遵循(22条记录) 提示(2.5米记录) 需要0041毫秒 select tips.id from tips where tips.users_id in (2,3,4,5,6,8,79407,38463,42798,94150,76554,56777,71407,51788,4624,41079,13549,75920,18979,6078,26178,18316) Bi
两个表,都有索引:
遵循(22条记录)
提示(2.5米记录) 需要0041毫秒
select tips.id
from tips
where tips.users_id in (2,3,4,5,6,8,79407,38463,42798,94150,76554,56777,71407,51788,4624,41079,13549,75920,18979,6078,26178,18316)
Bitmap Heap Scan on tips (cost=101.72..2122.76 rows=556 width=8) (actual time=0.267..1.120 rows=597 loops=1)
Recheck Cond: (users_id = ANY ('{2,3,4,5,6,8,79407,38463,42798,94150,76554,56777,71407,51788,4624,41079,13549,75920,18979,6078,26178,18316}'::bigint[]))
Heap Blocks: exact=594
-> Bitmap Index Scan on tips_idx_users_id01 (cost=0.00..101.58 rows=556 width=0) (actual time=0.188..0.188 rows=597 loops=1)
Index Cond: (users_id = ANY ('{2,3,4,5,6,8,79407,38463,42798,94150,76554,56777,71407,51788,4624,41079,13549,75920,18979,6078,26178,18316}'::bigint[]))
Planning time: 0.210 ms
Execution time: 1.193 ms
耗时1.2毫秒(第一次运行时为4.7毫秒)
需要10433毫秒定义:
CREATE TABLE public.follows (
id bigserial NOT NULL,
users_id_from bigint NOT NULL DEFAULT 0,
users_id_to bigint NOT NULL DEFAULT 0,
has_accepted boolean NOT NULL DEFAULT true,
created_on timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT followings_pkey
PRIMARY KEY (id)
)
CREATE TABLE public.tips (
id bigserial NOT NULL,
users_id bigint NOT NULL,
temp_id bigint NOT NULL,
first_seen numeric(12,2) NOT NULL DEFAULT 0,
created_on timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
expire_on_gmt timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
ip_from inet NOT NULL DEFAULT '0.0.0.0'::inet,
"type" smallint NOT NULL DEFAULT 0,
growth numeric(8,1) NOT NULL DEFAULT 0.0,
seen boolean DEFAULT false,
CONSTRAINT tips_pkey
PRIMARY KEY (id)
)
CREATE INDEX tips_idx_users_id01
ON public.tips
(users_id);
我真的不明白为什么性能这么差,似乎服务器在幕后进行了连接…任何帮助都将不胜感激 谢谢
佩雷斯 编辑-2018.10.9
尽管得到了公认的答案,但由于对Pavel Stehule的深入调查(见下文),世卫组织立即解决了问题,真正的问题是下表的统计数据不正确。真空分析解决了这个问题,现在两个queryes都运行得很快。我正在尝试测试用例,我得到了完全不同的计划: postgres=# explain analyze select * from foo where a in (select a from boo where b = 22); +------------------------------------------------------------------------------------------------------------------------------+ | QUERY PLAN | +------------------------------------------------------------------------------------------------------------------------------+ | Nested Loop (cost=16.19..7066.65 rows=2101 width=8) (actual time=0.444..11.667 rows=2713 loops=1) | | -> HashAggregate (cost=9.43..9.50 rows=7 width=4) (actual time=0.094..0.111 rows=9 loops=1) | | Group Key: boo.a | | -> Bitmap Heap Scan on boo (cost=4.33..9.42 rows=7 width=4) (actual time=0.048..0.071 rows=9 loops=1) | | Recheck Cond: (b = 22) | | Heap Blocks: exact=5 | | -> Bitmap Index Scan on boo_b_idx (cost=0.00..4.33 rows=7 width=0) (actual time=0.030..0.030 rows=9 loops=1) | | Index Cond: (b = 22) | | -> Bitmap Heap Scan on foo (cost=6.75..1005.16 rows=300 width=8) (actual time=0.256..1.143 rows=301 loops=9) | | Recheck Cond: (a = boo.a) | | Heap Blocks: exact=2678 | | -> Bitmap Index Scan on foo_a_idx (cost=0.00..6.68 rows=300 width=0) (actual time=0.145..0.145 rows=301 loops=9) | | Index Cond: (a = boo.a) | | Planning time: 0.971 ms | | Execution time: 12.105 ms ဠ | +------------------------------------------------------------------------------------------------------------------------------+ (15 rows) postgres=#解释分析选择*从foo中选择a,其中b=22(从boo中选择a); +------------------------------------------------------------------------------------------------------------------------------+ |查询计划| +------------------------------------------------------------------------------------------------------------------------------+ |嵌套循环(成本=16.19..7066.65行=2101宽度=8)(实际时间=0.444..11.667行=2713个循环=1)| |->HashAggregate(成本=9.43..9.50行=7宽度=4)(实际时间=0.094..0.111行=9循环=1)| |组键:boo.a| |->boo上的位图堆扫描(成本=4.33..9.42行=7宽度=4)(实际时间=0.048..0.071行=9个循环=1)| |复查条件:(b=22)| |堆块:精确=5| |->boo_b_idx上的位图索引扫描(成本=0.00..4.33行=7宽度=0)(实际时间=0.030..0.030行=9个循环=1)| |索引条件:(b=22)| |->foo上的位图堆扫描(成本=6.75..1005.16行=300宽度=8)(实际时间=0.256..1.143行=301循环=9)| |复查条件:(a=boo.a)| |堆块:精确=2678| |->foo_a_idx上的位图索引扫描(成本=0.00..6.68行=300宽度=0)(实际时间=0.145..0.145行=301循环=9)| |索引条件:(a=boo.a)| |计划时间:0.971毫秒| |执行时间:12.105毫秒ဠ | +------------------------------------------------------------------------------------------------------------------------------+ (15排) 虽然我惩罚了一些方法,但我得到了更好的计划- postgres=# explain analyze select * from foo where a in (select a from boo where b = 22); +----------------------------------------------------------------------------------------------------------------------------+ | QUERY PLAN | +----------------------------------------------------------------------------------------------------------------------------+ | Nested Loop (cost=18.03..7894.11 rows=2101 width=8) (actual time=0.433..9.809 rows=2713 loops=1) | | -> Unique (cost=17.60..17.63 rows=7 width=4) (actual time=0.384..0.407 rows=9 loops=1) | | -> Sort (cost=17.60..17.62 rows=7 width=4) (actual time=0.383..0.388 rows=9 loops=1) | | Sort Key: boo.a | | Sort Method: quicksort Memory: 25kB | | -> Seq Scan on boo (cost=0.00..17.50 rows=7 width=4) (actual time=0.047..0.358 rows=9 loops=1) | | Filter: (b = 22) | | Rows Removed by Filter: 991 | | -> Index Scan using foo_a_idx on foo (cost=0.43..1122.21 rows=300 width=8) (actual time=0.023..0.874 rows=301 loops=9) | | Index Cond: (a = boo.a) | | Planning time: 0.957 ms | | Execution time: 10.399 ms | +----------------------------------------------------------------------------------------------------------------------------+ (12 rows) postgres=#解释分析选择*从foo中选择a,其中b=22(从boo中选择a); +----------------------------------------------------------------------------------------------------------------------------+ |查询计划| +----------------------------------------------------------------------------------------------------------------------------+ |嵌套循环(成本=18.03..7894.11行=2101宽度=8)(实际时间=0.433..9.809行=2713个循环=1)| |->唯一(成本=17.60..17.63行=7宽度=4)(实际时间=0.384..0.407行=9圈=1)| |->排序(成本=17.60..17.62行=7宽度=4)(实际时间=0.383..0.388行=9个循环=1)| |排序键:boo.a| |排序方法:快速排序内存:25kB| |->boo上的顺序扫描(成本=0.00..17.50行=7宽度=4)(实际时间=0.047..0.358行=9个循环=1)| |过滤器:(b=22)| |被筛选器删除的行:991| |->在foo上使用foo_a_idx进行索引扫描(成本=0.43..1122.21行=300宽度=8)(实际时间=0.023..0.874行=301循环=9)| |索引条件:(a=boo.a)| |计划时间:0.957毫秒| |执行时间:10.399毫秒| +----------------------------------------------------------------------------------------------------------------------------+ (12排) 在PostgreSQL 10.5上测试 在玩了一些游戏之后,我得到了: +------------------------------------------------------------------------------------------------------------------------------------------------------+ | QUERY PLAN | +------------------------------------------------------------------------------------------------------------------------------------------------------+ | Gather (cost=1018.03..117733.71 rows=2101 width=8) (actual time=113.420..914.035 rows=2713 loops=1) | | Workers Planned: 2 | | Workers Launched: 2 | | -> Merge Semi Join (cost=18.03..116523.61 rows=875 width=8) (actual time=150.675..904.224 rows=904 loops=3) | | Merge Cond: (foo.a = boo.a) | | -> Parallel Index Scan using foo_a_idx on foo (cost=0.43..113510.99 rows=1250000 width=8) (actual time=0.136..800.463 rows=919564 loops=3) | | -> Sort (cost=17.60..17.62 rows=7 width=4) (actual time=0.347..0.357 rows=9 loops=3) | | Sort Key: boo.a | | Sort Method: quicksort Memory: 25kB | | -> Seq Scan on boo (cost=0.00..17.50 rows=7 width=4) (actual time=0.059..0.286 rows=9 loops=3) | | Filter: (b = 22) | | Rows Removed by Filter: 991 | | Planning time: 0.903 ms | | Execution time: 914.283 ms | +------------------------------------------------------------------------------------------------------------------------------------------------------+ (14 rows) +------------------------------------------------------------------------------------------------------------------------------------------------------+ |查询计划 postgres=# explain analyze select * from foo where a in (select a from boo where b = 22); +----------------------------------------------------------------------------------------------------------------------------+ | QUERY PLAN | +----------------------------------------------------------------------------------------------------------------------------+ | Nested Loop (cost=18.03..7894.11 rows=2101 width=8) (actual time=0.433..9.809 rows=2713 loops=1) | | -> Unique (cost=17.60..17.63 rows=7 width=4) (actual time=0.384..0.407 rows=9 loops=1) | | -> Sort (cost=17.60..17.62 rows=7 width=4) (actual time=0.383..0.388 rows=9 loops=1) | | Sort Key: boo.a | | Sort Method: quicksort Memory: 25kB | | -> Seq Scan on boo (cost=0.00..17.50 rows=7 width=4) (actual time=0.047..0.358 rows=9 loops=1) | | Filter: (b = 22) | | Rows Removed by Filter: 991 | | -> Index Scan using foo_a_idx on foo (cost=0.43..1122.21 rows=300 width=8) (actual time=0.023..0.874 rows=301 loops=9) | | Index Cond: (a = boo.a) | | Planning time: 0.957 ms | | Execution time: 10.399 ms | +----------------------------------------------------------------------------------------------------------------------------+ (12 rows) +------------------------------------------------------------------------------------------------------------------------------------------------------+ | QUERY PLAN | +------------------------------------------------------------------------------------------------------------------------------------------------------+ | Gather (cost=1018.03..117733.71 rows=2101 width=8) (actual time=113.420..914.035 rows=2713 loops=1) | | Workers Planned: 2 | | Workers Launched: 2 | | -> Merge Semi Join (cost=18.03..116523.61 rows=875 width=8) (actual time=150.675..904.224 rows=904 loops=3) | | Merge Cond: (foo.a = boo.a) | | -> Parallel Index Scan using foo_a_idx on foo (cost=0.43..113510.99 rows=1250000 width=8) (actual time=0.136..800.463 rows=919564 loops=3) | | -> Sort (cost=17.60..17.62 rows=7 width=4) (actual time=0.347..0.357 rows=9 loops=3) | | Sort Key: boo.a | | Sort Method: quicksort Memory: 25kB | | -> Seq Scan on boo (cost=0.00..17.50 rows=7 width=4) (actual time=0.059..0.286 rows=9 loops=3) | | Filter: (b = 22) | | Rows Removed by Filter: 991 | | Planning time: 0.903 ms | | Execution time: 914.283 ms | +------------------------------------------------------------------------------------------------------------------------------------------------------+ (14 rows)
select t.id
from tips t
where exists (select 1
from follows f
where f.users_id_from = 1 and f.users_id_to = t.users_id
);
with f as (
select users_id_to
from follows
where users_id_from = 1
)
select t.id
from tips t
where t.users_id in (select f.users_id_to from f);
select t.id
from tips t join
follows f
on f.users_id_to = t.id
where f.users_id_from = 1