一、构建测试数据

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. 【LeetCode动态规划#17】知道秘密的人,维护多个dp数组

    知道秘密的人数 在第 1 天,有一个人发现了一个秘密. 给你一个整数 delay ,表示每个人会在发现秘密后的 delay 天之后,每天 给一个新的人 分享 秘密.同时给你一个整数 forget ,表 ...

  2. 【Azure Developer】Go语言调用Azure SDK如何登录到中国区Azure环境

    问题描述 在 "使用 Azure SDK for Go 进行 Azure 身份验证" 文章中的 Go 示例代码进行登录Azure时,默认指向的是Globa Azure.当只修改AA ...

  3. 【Azure 应用服务】App Service 的.NET Version选择为.NET6,是否可以同时支持运行ASP.NET V4.8的应用呢?

    问题描述 App Service 的.NET Version选择为.NET6,是否可以同时支持运行ASP.NET V4.8的应用呢? 问题解答 答案是可以的,Azure App Service .NE ...

  4. [C++] does not name a type

    从网上找到了以下几点 https://blog.csdn.net/fly20180712/article/details/88306008 1.没有加调用函数的头文件 2.不存在xxx命名空间 3.包 ...

  5. SSK:超级键盘模拟器,调用底层,可模拟所有按键

    SSK - 吵架键盘模拟器 SuperSimulator of Keyboard 调用系统底层,能够模拟所有键盘操作! 本程序结合快Key(QuicKeys智能登录助手)一起使用,能够创造更多奇迹! ...

  6. XAF新手入门 - 数据字典示例

    前言 通过前面文章的介绍,大家应该对模块与类型信息子系统有所了解,再通过一个示例来加深大家对它的理解. 在准备写这个系列文章之前,就准备是概念+示例的组合,这样大家对概念的理解会更深刻.之前的规划是在 ...

  7. 软件架构(四)单体架构(Monolithic Architecture)

    系列目录 软件架构(一)概览 软件架构(二)编程语言的历史 软件架构(三)名词解释:架构.设计.风格.模式 软件架构(四)单体架构(Monolithic Architecture) 软件架构(五)分层 ...

  8. 一文学会JDBC实现java和mySQL的数据连接(尚硅谷学习课程代码+笔记+思路总结)

    JDBC是指数据库连接技术,用于java连接mySQL等数据库.本文详细介绍了尚硅谷课程中JDBC的学习内容和补充知识. 概述 java语言只提供规范接口,存在于java.sql.javax.sql包 ...

  9. modalError.vue 错误提示框 vue2 iview

    需求 一个错误提示框,后台需要有换行,默认没有换行,做一个支持换行的全局错误提示函数. 注意 代码只展示原理,直接不能使用,里面有getAc,有需要参考 https://www.cnblogs.com ...

  10. InputNumber 不能输入点 viewDesign 需求是 只能是整数

    <InputNumber ref="xxxRef" v-model="xxx" :disabled="xxx" style=" ...