一、构建测试数据

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设计模式-访问者模式Visitor

    介绍 访问者模式(Visitor Pattern),封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前 提下定义作用于这些元素的新的操作. 主要将数据结构与数据操作分离,解决 数据结 ...

  2. Innodb存储引擎之锁

    目录 一.概述 二.lock 与 latch 三.Innodb存储引擎中的锁 锁 一致性非锁定读 一致性锁定读 自增长与锁 外键与锁 四.锁的算法 锁的算法 Phantom Problem 幻读问题 ...

  3. 《深入理解Java虚拟机》(八) 记录一次OOM问题分析实战

    目录 一.问题分析思路 二.主要问题概述以及分析 1.相关操作 2.主要问题现象 3.初步分析问题 三.相关工具介绍 四.实际问题快照分析 1.通过Memory查看老年代内存占用情况 2.选择Live ...

  4. 【Android 抓包对抗】代理检查绕过

    1. 安装apk,点进去发现一点就挂 2. apk 拖入到jadx中观察,发现多出检查,一旦满足条件就会退出 .... if (((ConnectivityManager) getSystemServ ...

  5. mac更新系统后,提示xcrun的错误问题

    pycharm运行代码终端报错: xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), ...

  6. 【LeetCode栈与队列#05】滑动窗口最大值

    滑动窗口最大值 力扣题目链接(opens new window) 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口 ...

  7. 基于 Nebula Graph 构建图学习能力

    本文首发于 Nebula Graph Community 公众号 经常看技术文章的小伙伴可能会留意到除了正在阅读的那篇文章,在文章页面的正文下方或者右侧区域会有若干同主题.同作者的文章等你阅读:经常逛 ...

  8. centos下配置修改hosts文件以及生效命令详解

    linux服务器hosts文件配置 hosts文件是Linux系统中一个负责IP地址与域名快速解析的文件,以ASCII格式保存在"/etc"目录下,文件名为"hosts& ...

  9. Codeforces Round 926 (Div. 2)(A~D)

    目录 A B C D A 输出最大值减最小值,或者排序算一下答案 #include <bits/stdc++.h> #define int long long #define rep(i, ...

  10. 使用 Docker 部署 Next Terminal 轻量级堡垒机

    1)Next Terminal 介绍 官网:https://next-terminal.typesafe.cn/ GitHub:https://github.com/dushixiang/next-t ...