KingabseES执行计划-分区剪枝(partition pruning)
概述
分区修剪(Partition Pruning)是分区表性能的查询优化技术 。在分区修剪中,优化器分析SQL语句中的FROM和WHERE子句,以在构建分区访问列表时消除不需要的分区。此功能使数据库只能在与SQL语句相关的分区上执行操作。
参数 enable_partition_pruning 设置启用或禁用分区剪枝。
分区修剪的好处
分区修剪大大减少了从磁盘检索的数据量,缩短了处理时间,从而提高了查询性能并优化了资源利用率。
根据实际的SQL语句,Kingbase数据库可使用静态或动态修剪。静态修剪发生在编译时,预先访问有关分区的信息。动态修剪发生在运行时,这意味着语句要访问的确切分区事先是未知的。静态修剪的示例场景是一个SQL语句,该语句包含一个WHERE条件,分区键列上有一个常量文本。动态修剪的一个例子是在WHERE条件中使用运算符或函数。
可用于分区修剪的信息
可以对分区列执行分区修剪。
当您在范围或列表分区列上使用range、LIKE、 = 和IN列表谓词时,以及当您在哈希分区列中使用 = 或 IN列表谓词后,Kingbase数据库将修剪分区。
对于多级分区对象,Kingbase数据库可以使用相关谓词在每个级别上进行修剪。
Kingbase使用分区列上的谓词执行分区修剪,如下所示:
- 当使用范围分区时,Kingbase只访问分区p2和p3,表示2020年二月和三月的分区。
- 当使用哈希子分区时,Kingbase只访问每个分区中存储productid=100行的一个子分区。子分区和谓词之间的映射是基于Kingbase的内部哈希分布函数计算的。
CREATE TABLE orders_range_hash
(
productid int,
saledate DATE,
custid int,
totalprice numeric
)
PARTITION BY RANGE (saledate) SUBPARTITION BY HASH (productid) SUBPARTITIONS 8
(PARTITION p1 VALUES LESS THAN
(TO_DATE('2020-01-01', 'YYYY-MM-DD')),
PARTITION p2 VALUES LESS THAN
(TO_DATE('2022-02-01', 'YYYY-MM-DD')),
PARTITION p3 VALUES LESS THAN
(TO_DATE('2022-03-01', 'YYYY-MM-DD')),
PARTITION p4 VALUES LESS THAN
(TO_DATE('2022-04-01', 'YYYY-MM-DD')));
SELECT *
FROM orders_range_hash
WHERE saledate BETWEEN (TO_DATE('2020-01-10', 'YYYY-MM-DD')) AND (TO_DATE('2020-02-11', 'YYYY-MM-DD'))
AND productid = 100;
如何确定是否已使用分区修剪
不仅在给定查询的规划期间可以执行分区剪枝,在其执行期间也能执行分区剪枝。 这非常有用,因为如果子句中包含查询规划时值未知的表达式时,这可以剪枝掉更多的分区; 例如在PREPARE
语句中定义的参数会使用从子查询拿到的值,或者嵌套循环连接内侧关系上的参数化值。 执行期间的分区剪枝可能在下列任何时刻执行:
- 在查询计划的初始化期间。对于执行的初始化阶段就已知值的参数,可以在这里执行分区剪枝。这个阶段中被剪枝掉的分区将不会显示在查询的
EXPLAIN
或EXPLAIN ANALYZE
结果中。通过观察EXPLAIN
输出的“Subplans Removed”属性,可以确定被剪枝掉的分区数。 - 在查询计划的实际执行期间。这里可以使用只有在实际查询执行时才能知道的值执行分区剪枝。这包括来自子查询的值以及来自执行时参数的值(例如来自于参数化嵌套循环连接的参数)。由于在查询执行期间这些参数的值可能会改变多次,所以只要分区剪枝使用到的执行参数发生改变,就会执行一次分区剪枝。要判断分区是否在这个阶段被剪枝,需要仔细地观察
EXPLAIN ANALYZE
输出中的loops
属性。 对应于不同分区的子计划可以具有不同的值,这取决于在执行期间每个分区被修剪的次数。 如果每次都被剪枝,有些分区可能会显示为(never executed)
。
静态分区修剪
根据静态谓词确定何时使用静态修剪。
在许多情况下,优化器确定编译时要访问的分区。如果使用静态谓词,则会发生静态分区修剪。
如果在解析时,优化器可以识别访问的连续分区集,则执行计划中,将显示正在访问的分区的条件范围。
CREATE TABLE orders_list
(
productid int,
saledate DATE,
custid int,
totalprice numeric
)
PARTITION BY LIST (custid)
(PARTITION p1 VALUES (1,2),
PARTITION p2 VALUES (3,4),
PARTITION p2 VALUES (5,6));
explain analyzed
select * from orders_list
where custid = 3;
Seq Scan on orders_list_p2 (cost=0.00..23.38 rows=5 width=48) (actual time=0.016..0.020 rows=17 loops=1)
Filter: (custid = 3)
Rows Removed by Filter: 17
Planning Time: 0.107 ms
Execution Time: 0.037 ms
动态分区修剪
如果可以修剪,但无法进行静态修剪,则进行动态修剪,因为分区键值仅在执行时获知。
使用绑定变量进行动态修剪
对分区列使用绑定变量的语句会导致动态修剪。
\set vid 4
explain select * from orders_list where custid = :vid;
QUERY PLAN
----------------------------------------------------------------
Seq Scan on orders_list_p2 (cost=0.00..23.38 rows=5 width=48)
Filter: (custid = 4)
(2 行记录)
do
$$
declare
c1 text;
begin
for c1 in execute 'explain select * from orders_list where custid = :vid' using (random() * 10)::int % 6 + 1
loop
raise info '%',c1;
end loop;
end;
$$;
信息: Seq Scan on orders_list_p1 (cost=0.00..23.38 rows=5 width=48)
信息: Filter: (custid = 2)
ANONYMOUS BLOCK
使用子查询进行动态修剪
对分区列显式使用子查询的语句会导致动态修剪。
分区节点的(never executed),表示执行了分区修剪。如果过滤条件使用IN子查询,则不能分区修剪。
explain (costs off,analyze)
with v as (select (random() * 10)::int % 2 + 1 id)
select *
from orders_list
where custid = (select v.id from v);
QUERY PLAN
-----------------------------------------------------------------------------
Append (actual time=0.028..0.033 rows=17 loops=1)
CTE v
-> Result (actual time=0.004..0.004 rows=1 loops=1)
InitPlan 2 (returns $1)
-> CTE Scan on v (actual time=0.007..0.008 rows=1 loops=1)
-> Seq Scan on orders_list_p1 (actual time=0.015..0.018 rows=17 loops=1)
Filter: (custid = $1)
Rows Removed by Filter: 16
-> Seq Scan on orders_list_p2 (never executed)
Filter: (custid = $1)
-> Seq Scan on orders_list_p3 (never executed)
Filter: (custid = $1)
Planning Time: 0.172 ms
Execution Time: 0.069 ms
(14 行记录)
explain (costs off,analyze)
with v as (select (random() * 10)::int % 2 + 1 id)
select *
from orders_list
where custid in (select v.id from v);
QUERY PLAN
-----------------------------------------------------------------------------------
Hash Semi Join (actual time=0.046..0.067 rows=16 loops=1)
Hash Cond: (orders_list_p1.custid = v.id)
CTE v
-> Result (actual time=0.005..0.005 rows=1 loops=1)
-> Append (actual time=0.009..0.023 rows=100 loops=1)
-> Seq Scan on orders_list_p1 (actual time=0.008..0.010 rows=33 loops=1)
-> Seq Scan on orders_list_p2 (actual time=0.003..0.004 rows=34 loops=1)
-> Seq Scan on orders_list_p3 (actual time=0.002..0.004 rows=33 loops=1)
-> Hash (actual time=0.012..0.012 rows=1 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 9kB
-> CTE Scan on v (actual time=0.008..0.008 rows=1 loops=1)
Planning Time: 0.303 ms
Execution Time: 0.095 ms
(13 行记录)
具有关联需求的动态修剪
等于(=)谓词,限制子查询的结果只能有一行。IN 、EXISTS、ANY 等方式,使用子查询时,不能执行动态修剪。多表连接,也不能执行动态修剪。
这种不能使用动态修剪的情况,可以使用LATERAL语法解决。
LATERAL子查询不能是简单子查询。
explain (costs off ,analyze)
with t (id) as (values (1), (2))
select *
from t
, lateral ( select * from orders_list t1 where t1.custid = t.id limit all) t1;
QUERY PLAN
--------------------------------------------------------------------------------------
Nested Loop (actual time=0.022..0.037 rows=33 loops=1)
-> Values Scan on "*VALUES*" (actual time=0.002..0.003 rows=2 loops=1)
-> Append (actual time=0.009..0.013 rows=16 loops=2)
-> Seq Scan on orders_list_p1 t1 (actual time=0.007..0.009 rows=16 loops=2)
Filter: (custid = "*VALUES*".column1)
Rows Removed by Filter: 16
-> Seq Scan on orders_list_p2 t1_1 (never executed)
Filter: (custid = "*VALUES*".column1)
-> Seq Scan on orders_list_p3 t1_2 (never executed)
Filter: (custid = "*VALUES*".column1)
Planning Time: 0.189 ms
Execution Time: 0.072 ms
分区修剪提示
使用分区修剪时,应考虑以下事项:
数据类型转换
若要从分区修剪中获得最大的性能优势,应避免使用需要数据库转换指定数据类型的构造。
函数调用
避免在分区列上使用隐式或显式函数。如果您的查询通常使用函数调用,请考虑在这些情况下使用虚拟列和虚拟列分区,以从分区修剪中受益。
KingabseES执行计划-分区剪枝(partition pruning)的更多相关文章
- 高性能可扩展mysql 笔记(六) SQL执行计划及分页查询优化、分区键统计
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 常见业务处理 一.使用数据库处理常见业务: 案例: 如何对评论进行分页展示 使用 EXPLAIN 获得s ...
- MYSQL EXPLAIN执行计划命令详解(支持更新中)
本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 摘要: 本篇是根据官网中的每个一点来翻译.举例.验证的:英语不好,所 ...
- MySQL-EXPLAIN执行计划Extra解释
EXPLAIN命令输出的列中Extra字段可选值较多,这里单独说一下. 该Extra列 EXPLAIN输出包含MySQL解决查询的额外信息.以下列表说明了此列中可能出现的值.每个项目还指示JSON格式 ...
- PostgreSQL 与 Oracle 访问分区表执行计划差异
熟悉Oracle 的DBA都知道,Oracle 访问分区表时,对于没有提供分区条件的,也就是在无法使用分区剪枝情况下,优化器会根据全局的统计信息制定执行计划,该执行计划针对所有分区适用.在分析利弊之前 ...
- 分析oracle的执行计划(explain plan)并对对sql进行优化实践
基于oracle的应用系统很多性能问题,是由应用系统sql性能低劣引起的,所以,sql的性能优化很重要,分析与优化sql的性能我们一般通过查看该sql的执行计划,本文就如何看懂执行计划,以及如何通过分 ...
- 怎样看懂Oracle的执行计划
怎样看懂Oracle的执行计划 一.什么是执行计划 An explain plan is a representation of the access path that is taken when ...
- oracle执行计划之-表连接方式
转载自:http://blog.csdn.net/tianlesoftware/article/details/5826546 在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的 ...
- Mysql执行计划说明
Mysql执行计划翻译: 官网原文请见http://dev.mysql.com/doc/refman/5.6/en/explain-output.html:5.6 EXPLAIN语句提供有关SELEC ...
- Oracle中SQL调优(SQL TUNING)之最权威获取SQL执行计划大全
该文档为根据相关资料整理.总结而成,主要讲解Oracle数据库中,获取SQL语句执行计划的最权威.最正确的方法.步骤,此外,还详细说明了每种方法中可选项的意义及使用方法,以方便大家和自己日常工作中查阅 ...
- hive高阶1--sql和hive语句执行顺序、explain查看执行计划、group by生成MR
hive语句执行顺序 msyql语句执行顺序 代码写的顺序: select ... from... where.... group by... having... order by.. 或者 from ...
随机推荐
- Delphi 实现刘谦春晚魔术
看了博友的C# 实现刘谦春晚魔术很好,改成了delphi版的. 1 program Project1; 2 3 {$APPTYPE CONSOLE} 4 {$R *.res} 5 6 uses 7 S ...
- Java I/O 教程(五) BufferedOutputStream 类
Java BufferedOutputStream Class Java BufferedOutputStream class 用于缓冲一个输出流 其内部使用缓冲区存储数据,可以更有效率的往流中写入数 ...
- Qt开发Activex笔记(三):C#调用Qt开发的Activex控件
若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113789727 长期持续带来更多项目与技术分享 ...
- 通过 saltstack 批量更新 SSL 证书
哈喽大家好,我是咸鱼. 之前写过两篇关于 SSL 过期巡检脚本的文章: SSL 证书过期巡检脚本 SSL 证书过期巡检脚本(Python 版) 这两篇文章都是讲如何通过脚本去自动检测 SSL 过期时间 ...
- 类型注解Callable
from collections.abc import Callable """ Callable[[ParamType1, ParamType2], ReturnTyp ...
- Linux Cheat Sheet
- 答对这 9 题你就超越了 83.3% 的图数据库 NebulaGraph 用户
熟悉 NebulaGraph 社区的小伙伴可能都知道一个技能认证叫做:NGCP,全称 NebulaGraph Certified Professional.用户在考试认证期间在 1 个小时内回答 10 ...
- 标准差为什么除以n-1
参考:https://blog.csdn.net/qian2213762498/article/details/80558018 如果要测量中国人的平均身高,假设为μ,通常会随机取假设10000人,求 ...
- 闭关修炼180天----手写迷你版的tomcat-Minicat
手写迷你版的tomcat-Minicat 小谈Tomcat Tomcat请求处理⼤致过程 Tomcat是⼀个Http服务器(能够接收并且处理http请求,所以tomcat是⼀个http服务器) 我们使 ...
- Linux性能监控(二)-top
top命令可以用来监控服务器CPU.内存的运行情况,是Linux一个经常使用到的命令. 基本用法 第一行 显示当前系统运行信息,系统当前时间是23:23:21,运行了315days,当前有2个用户登录 ...