PostgreSQL 函数稳定性在索引与全表访问下的性能差异
一、构建测试数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | create or replace function test_volatile(id integer ) returns bigint volatile language sql as $$ select count (*) from t1 $$ ; / create or replace function test_stable(id integer ) returns bigint stable language sql as $$ select count (*) from t1 $$ ; / create or replace function test_immutable(id integer ) returns bigint immutable language sql as $$ select count (*) from t1 $$ ; / insert into test select 1 from generate_series(1,1000); |
二、没有索引情况下执行性能
这里的索引是指 test(id) 索引,显然,因为 id 值都是相同的,这里的索引实际意义不大。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | test=# explain analyze select count (*) from test where id=test_volatile(1); QUERY PLAN ----------------------------------------------------------------------------------------------------------------- Aggregate (cost=270.00..270.01 rows =1 width=8) (actual time =16154.566..16154.566 rows =1 loops=1) -> Seq Scan on test (cost=0.00..267.50 rows =1000 width=0) (actual time =16154.564..16154.564 rows =0 loops=1) Filter: (id = test_volatile(1)) Rows Removed by Filter: 1000 Planning Time : 0.165 ms Execution Time : 16154.585 ms (6 rows ) Time : 16155.404 ms (00:16.155) test=# test=# explain analyze select count (*) from test where id=test_stable(1); QUERY PLAN -------------------------------------------------------------------------------------------------------------- Aggregate (cost=267.50..267.51 rows =1 width=8) (actual time =16401.441..16401.441 rows =1 loops=1) -> Seq Scan on test (cost=0.00..267.50 rows =1 width=0) (actual time =16401.439..16401.439 rows =0 loops=1) Filter: (id = test_stable(1)) Rows Removed by Filter: 1000 Planning Time : 28.010 ms Execution Time : 16401.473 ms (6 rows ) Time : 16430.319 ms (00:16.430) test=# explain analyze select count (*) from test where id=test_immutable(1); QUERY PLAN ----------------------------------------------------------------------------------------------------- Aggregate (cost=17.50..17.51 rows =1 width=8) (actual time =0.065..0.065 rows =1 loops=1) -> Seq Scan on test (cost=0.00..17.50 rows =1 width=0) (actual time =0.064..0.064 rows =0 loops=1) Filter: (id = '100000' :: bigint ) Rows Removed by Filter: 1000 Planning Time : 44.469 ms Execution Time : 0.083 ms (6 rows ) Time : 45.197 ms |
三、创建索引情况下的执行性能
create index idx_test_id on test(id);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | test=# explain analyze select count (*) from test where id=test_volatile(1); QUERY PLAN ----------------------------------------------------------------------------------------------------------------- Aggregate (cost=270.00..270.01 rows =1 width=8) (actual time =16497.225..16497.226 rows =1 loops=1) -> Seq Scan on test (cost=0.00..267.50 rows =1000 width=0) (actual time =16497.223..16497.223 rows =0 loops=1) Filter: (id = test_volatile(1)) Rows Removed by Filter: 1000 Planning Time : 0.438 ms Execution Time : 16497.258 ms (6 rows ) Time : 16498.229 ms (00:16.498) test=# explain analyze select count (*) from test where id=test_stable(1); QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- Aggregate (cost=4.55..4.56 rows =1 width=8) (actual time =17.419..17.419 rows =1 loops=1) -> Index Only Scan using idx_test_id on test (cost=0.53..4.54 rows =1 width=0) (actual time =17.417..17.417 rows =0 loops=1) Index Cond: (id = test_stable(1)) Heap Fetches: 0 Planning Time : 16.875 ms Execution Time : 17.511 ms (6 rows ) Time : 34.742 ms test=# explain analyze select count (*) from test where id=test_immutable(1); QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- Aggregate (cost=4.30..4.31 rows =1 width=8) (actual time =0.011..0.011 rows =1 loops=1) -> Index Only Scan using idx_test_id on test (cost=0.28..4.29 rows =1 width=0) (actual time =0.009..0.009 rows =0 loops=1) Index Cond: (id = '100000' :: bigint ) Heap Fetches: 0 Planning Time : 18.673 ms Execution Time : 0.032 ms (6 rows ) Time : 19.042 ms |
四、结论
1、对于 volatile 类型的函数,由于不同时刻函数结果可能不同,从安全角度需要逐行调用函数。
2、这里重点关注的 test_stable 函数:使用全表扫描,每行都要执行一次。使用索引,只需执行一次。
KINGBASE研究院
分类:
性能相关
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!