一、构建测试数据

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 函数稳定性在索引与全表访问下的性能差异的更多相关文章

  1. mysql-update时where条件无索引锁全表

          1 5.3日数据处理需求 UPDATE md_meter set warranty_end_date = DATE_ADD(warranty_begin_date,INTERVAL 10 ...

  2. MYSQl 全表扫描以及查询性能

    MYSQl 全表扫描以及查询性能 -- 本文章仅用于学习,记录 一. Mysql在一些情况下全表检索比索引查询更快: 1.表格数据很少,使用全表检索会比使用索引检索更快.一般当表格总数据小于10行并且 ...

  3. sql语句优化:尽量使用索引避免全表扫描

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  4. Oracle 数据库禁止全表访问的时候direct path read /////

    一般在OLAP环境中,大表在进行全表扫描的时候一般会出现direct path read等待事件,如果在OLTP环境中,出现大量的direct path read直接路径读取,这样就有问题了.一般在O ...

  5. ABAP 内表访问表达式的性能

    内表访问表达式是ABAP 7.4中引入的重要特性,可以使语句变得更加简洁.美观.那么它的读写性能怎么样呢?我进行了一点点测试. 读取 测试代码,使用三种方式读取同一内表,分别是read table关键 ...

  6. postgresql函数:满足特定格式的表及指定日期前的删除

    -- 一.现有函数-- 1.现有函数调用select "ap"."delete_analysis_backup"('ap');-- 2.函数内容CREATE O ...

  7. MySQL 没有索引 锁全表

    <h3 class="title" style="box-sizing: inherit; margin: 8px 0px 15px; padding: 0px; ...

  8. SQL 数据优化索引建suo避免全表扫描

    首先什么是全表扫描和索引扫描?全表扫描所有数据过一遍才能显示数据结果,索引扫描就是索引,只需要扫描一部分数据就可以得到结果.如果数据没建立索引. 无索引的情况下搜索数据的速度和占用内存就会比用索引的检 ...

  9. 索引法则--LIKE以%开头会导致索引失效进而转向全表扫描(使用覆盖索引解决)

    Mysql 系列文章主页 =============== 1 准备数据 1.1 建表 DROP TABLE IF EXISTS staff; CREATE TABLE IF NOT EXISTS st ...

  10. MySQL 索引优化全攻略

    所谓索引就是为特定的mysql字段进行一些特定的算法排序,比如二叉树的算法和哈希算法,哈希算法是通过建立特征值,然后根据特征值来快速查找.而用的最多,并且是mysql默认的就是二叉树算法 BTREE, ...

随机推荐

  1. Java并发编程实例--17.使用read/write锁同步数据访问

    锁机制带来的最有意义的改进是提供了ReadWriteLock接口及其实现类ReentrantReadWriteLock. 这个类有2个锁,一个针对读操作另一个针对写操作. 可以有多个线程使用读操作,但 ...

  2. Jenkins共享库使用

    简单使用 共享库(Shared libraries)是一种可以用来封装函数.变量甚至整个 Pipeline 的机制.通过共享库,可以将常用的功能和流程逻辑定义在单独的 Groovy 脚本中,然后在多个 ...

  3. 02-Redis系列之-架构和高级API的使用

    通用部分 通用命令 # 1-keys # 打印出所有key keys * # 打印出所有以n开头的key keys n* # 打印出所有以nam开头,第四个字母是a到z的范围 keys nam[a-z ...

  4. 矩池云上 git clone --recursive 出错,怎么解决

    遇到问题 有时候安装包教程里 git clone 的时候会出现以下错误: git clone --recursive https://github.91chi.fun/https://github.c ...

  5. 【Azure 应用服务】App Service for Linux环境中,如何解决字体文件缺失的情况

    问题描述 部署在App Service for Linux环境中的Web App.出现了字体文件缺失的问题,页面显示本来时中文的地方,区别变为方框占位. 问题分析 在应用中,通常涉及到显示问题的有两个 ...

  6. Binlog分析利器-binlog_summary.py

    ​Binlog中,除了具体的SQL,其实,还包含了很多有价值的信息,如, 事务的开始时间. 事务的结束时间. 事务的开始位置点. 事务的结束位置点. 操作的开始时间(一个事务通常会包含多个操作). 表 ...

  7. 今天接到一个根据excel来更新数据库的需求,用php写个小脚本

    需求大概内容是,excel中有些条目需要删除.有些需要新增,就需要基于这份excel生成删.增的SQL. 要求是这样的:蓝色要删除的,黄色是要新增的,白色和灰色的不用管. 我第一时间就在想:还得识别单 ...

  8. Java 子类对象实例化的全过程

    2 /* 3 * 子类对象实例化的全过程 4 * 5 *1.结果上来看:(继承性) 6 * 子类继承父类以后,就获取了父类中声明的属性或方法 7 * 创建子类的对象,在堆空间中,就会加载所有父类声明的 ...

  9. win10图标异常显示空白,WiFi图标消失等情况解决方案

    出现WiFi图标异常不显示,但是网络却正常,以下为解决方案: Win + R 快捷键调出运行框,输入%USERPROFILE%\AppData\Local,找到IconCache.db文件并删除,之后 ...

  10. 一键Run带你体验扩散模型的魅力

    本文分享自华为云社区<爆圈Sora横空出世,AGI通用人工智能时代真的要来了吗?一键Run带你体验扩散模型的魅力!>,作者: 码上开花_Lancer. Sora这几天的爆炸性新闻,让所有人 ...