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, ...
随机推荐
- SVG与foreignObject元素
SVG与foreignObject元素 可缩放矢量图形Scalable Vector Graphics - SVG基于XML标记语言,用于描述二维的矢量图形.作为一个基于文本的开放网络标准,SVG能够 ...
- Js中数组空位问题
Js中数组空位问题 JavaScript中数组空位指的是数组中的empty,其表示的是在该位置没有任何值,而且empty是区别于undefined的,同样empty也不属于Js的任何数据类型,并且在J ...
- 开源:Taurus.DistributedLock 分布式锁框架,支持 .Net 和 .Net Core 双系列版本
前言: 在经过漫长的技术沉淀,终于又为 .Net 及 .Net Core 的微服务系列框架贡献当中的一个重要组件. Taurus.DistributedLock is a distributed lo ...
- r0tracer 源码分析
使用方法 修改r0tracer.js文件最底部处的代码,开启某一个Hook模式. function main() { Java.perform(function () { console.Purple ...
- glob模块(匹配所有符合条件的文件)
函数功能介绍 匹配所有的符合条件的文件,并将其以list的形式返回. 通配符 "*":匹配零个或多个字符 "?":匹配任何单个字符 "[]" ...
- .NET Core 集成微信支付签名错误
.NET Core 集成微信支付签名错误 The provided data is tagged with 'Universal' class value '16', but it should ha ...
- 【LeetCode动态规划#01】动规入门:求斐波那契数 + 爬楼梯 + 最小代价爬楼梯(熟悉解题方法论)
斐波那契数 力扣题目链接(opens new window) 斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 .该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和.也就 ...
- ubuntu22.04安装配置redis
本操作在虚拟机上 安装Redis 1)更新系统 sudo apt update sudo apt upgrade 2)安装Redis sudo apt install redis-server 3)测 ...
- RocketMQ(9) 消息堆积与消费延迟
消息堆积与消费延迟 1 概念 消息处理流程中,如果Consumer的消费速度跟不上Producer的发送速度,MQ中未处理的消息会越来越多(进的多出的少),这部分消息就被称为堆积消息.消息出现堆积进而 ...
- Java //输入两个正整数m和n,求其最大的公约数和最小公倍数//12和20的最大公约数是4,最小公倍数是60
1 //输入两个正整数m和n,求其最大的公约数和最小公倍数 2 //12和20的最大公约数是4,最小公倍数是60 3 4 Scanner scan = new Scanner(System.in); ...