PostgreSQL 函数稳定性在索引与全表访问下的性能差异
一、构建测试数据
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 值都是相同的,这里的索引实际意义不大。
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);
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 函数:使用全表扫描,每行都要执行一次。使用索引,只需执行一次。
PostgreSQL 函数稳定性在索引与全表访问下的性能差异的更多相关文章
- mysql-update时where条件无索引锁全表
1 5.3日数据处理需求 UPDATE md_meter set warranty_end_date = DATE_ADD(warranty_begin_date,INTERVAL 10 ...
- MYSQl 全表扫描以及查询性能
MYSQl 全表扫描以及查询性能 -- 本文章仅用于学习,记录 一. Mysql在一些情况下全表检索比索引查询更快: 1.表格数据很少,使用全表检索会比使用索引检索更快.一般当表格总数据小于10行并且 ...
- sql语句优化:尽量使用索引避免全表扫描
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- Oracle 数据库禁止全表访问的时候direct path read /////
一般在OLAP环境中,大表在进行全表扫描的时候一般会出现direct path read等待事件,如果在OLTP环境中,出现大量的direct path read直接路径读取,这样就有问题了.一般在O ...
- ABAP 内表访问表达式的性能
内表访问表达式是ABAP 7.4中引入的重要特性,可以使语句变得更加简洁.美观.那么它的读写性能怎么样呢?我进行了一点点测试. 读取 测试代码,使用三种方式读取同一内表,分别是read table关键 ...
- postgresql函数:满足特定格式的表及指定日期前的删除
-- 一.现有函数-- 1.现有函数调用select "ap"."delete_analysis_backup"('ap');-- 2.函数内容CREATE O ...
- MySQL 没有索引 锁全表
<h3 class="title" style="box-sizing: inherit; margin: 8px 0px 15px; padding: 0px; ...
- SQL 数据优化索引建suo避免全表扫描
首先什么是全表扫描和索引扫描?全表扫描所有数据过一遍才能显示数据结果,索引扫描就是索引,只需要扫描一部分数据就可以得到结果.如果数据没建立索引. 无索引的情况下搜索数据的速度和占用内存就会比用索引的检 ...
- 索引法则--LIKE以%开头会导致索引失效进而转向全表扫描(使用覆盖索引解决)
Mysql 系列文章主页 =============== 1 准备数据 1.1 建表 DROP TABLE IF EXISTS staff; CREATE TABLE IF NOT EXISTS st ...
- MySQL 索引优化全攻略
所谓索引就是为特定的mysql字段进行一些特定的算法排序,比如二叉树的算法和哈希算法,哈希算法是通过建立特征值,然后根据特征值来快速查找.而用的最多,并且是mysql默认的就是二叉树算法 BTREE, ...
随机推荐
- elasticsearch should实现or功能,设置minimum_should_match
elasticsearch实现传统数据库中的or功能,需要使用bool下面的should关键字,对于A or B的情况,应该至少返回A和B中的一个,但是如下语句,不仅返回A和B中的至少一个,也返回了没 ...
- C++ std::move 的一些问题
看 SO 上有一个比较奇怪的问题, When does an rvalue reference result in a move vs copy constructor and why? 问题代码: ...
- SetWindowHookEx的复习
#include <Windows.h> #include <iostream> using namespace std; HHOOK keyboardHook; LRESUL ...
- 【Android逆向】破解看雪9月算法破解第一题
1. 安装apk到手机 2. 随意输入账号和密码,点击register,报错crackme1:ERROR 3. 将apk拖入到jadx中进行观察 public native String regist ...
- Redis客户端汇总
编程客户端 已经支持了许多编程语言,详见:https://redis.io/docs/clients/ 图形客户端 1.Another Redis Desktop Manager 支持哨兵, 集群, ...
- VS Code实现SSH远程开发
最近收获一台新台式机,但是个人主要还是使用自己的笔记本,用了几天远程控制,感觉各种不方便,最终决定配置一下VS Code实现SSH远程开发,特此记录. 首先介绍一下环境,控制端是Windows 11, ...
- 【Azure Function】修改Function执行的Timeout时间
问题描述 Azure Function默认的Timeout时间是否可以调整呢? 问题解答 可以的,根据创建Function的时候选择的定价层不同,Function 默认的Timeout时间也不同. 消 ...
- 【Azure 事件中心】Flink消费Event Hub中事件, 使用Azure默认示例代码,始终获取新产生的事件,如何消费旧事件呢?
问题描述 根据Azure Event Hub示例文档,[将 Apache Flink 与适用于 Apache Kafka 的 Azure 事件中心配合使用],配置好 consumer.config 文 ...
- Frechet Inception Distance
(以下内容重新更新,主要讲解FID的意义,为何FID能够表示生成图像的多样性和质量,为什么FID越小,则图像多样性越好,质量也越好) 在计算FID中我们也同样使用inception network网络 ...
- MAUI调用.so库
必要条件: (一)安装JDK (二)安装NDK (三)安装Android Studio(其实可以不用装也行) 使用Android Studio构件.so包 构件.so包 1. 使用Android st ...