概述

分区修剪(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语句中定义的参数会使用从子查询拿到的值,或者嵌套循环连接内侧关系上的参数化值。 执行期间的分区剪枝可能在下列任何时刻执行:

  • 在查询计划的初始化期间。对于执行的初始化阶段就已知值的参数,可以在这里执行分区剪枝。这个阶段中被剪枝掉的分区将不会显示在查询的EXPLAINEXPLAIN 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)的更多相关文章

  1. 高性能可扩展mysql 笔记(六) SQL执行计划及分页查询优化、分区键统计

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 常见业务处理 一.使用数据库处理常见业务: 案例: 如何对评论进行分页展示 使用 EXPLAIN 获得s ...

  2. MYSQL EXPLAIN执行计划命令详解(支持更新中)

    本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 摘要: 本篇是根据官网中的每个一点来翻译.举例.验证的:英语不好,所 ...

  3. MySQL-EXPLAIN执行计划Extra解释

    EXPLAIN命令输出的列中Extra字段可选值较多,这里单独说一下. 该Extra列 EXPLAIN输出包含MySQL解决查询的额外信息.以下列表说明了此列中可能出现的值.每个项目还指示JSON格式 ...

  4. PostgreSQL 与 Oracle 访问分区表执行计划差异

    熟悉Oracle 的DBA都知道,Oracle 访问分区表时,对于没有提供分区条件的,也就是在无法使用分区剪枝情况下,优化器会根据全局的统计信息制定执行计划,该执行计划针对所有分区适用.在分析利弊之前 ...

  5. 分析oracle的执行计划(explain plan)并对对sql进行优化实践

    基于oracle的应用系统很多性能问题,是由应用系统sql性能低劣引起的,所以,sql的性能优化很重要,分析与优化sql的性能我们一般通过查看该sql的执行计划,本文就如何看懂执行计划,以及如何通过分 ...

  6. 怎样看懂Oracle的执行计划

    怎样看懂Oracle的执行计划 一.什么是执行计划 An explain plan is a representation of the access path that is taken when ...

  7. oracle执行计划之-表连接方式

    转载自:http://blog.csdn.net/tianlesoftware/article/details/5826546 在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的 ...

  8. Mysql执行计划说明

    Mysql执行计划翻译: 官网原文请见http://dev.mysql.com/doc/refman/5.6/en/explain-output.html:5.6 EXPLAIN语句提供有关SELEC ...

  9. Oracle中SQL调优(SQL TUNING)之最权威获取SQL执行计划大全

    该文档为根据相关资料整理.总结而成,主要讲解Oracle数据库中,获取SQL语句执行计划的最权威.最正确的方法.步骤,此外,还详细说明了每种方法中可选项的意义及使用方法,以方便大家和自己日常工作中查阅 ...

  10. hive高阶1--sql和hive语句执行顺序、explain查看执行计划、group by生成MR

    hive语句执行顺序 msyql语句执行顺序 代码写的顺序: select ... from... where.... group by... having... order by.. 或者 from ...

随机推荐

  1. Delphi 实现刘谦春晚魔术

    看了博友的C# 实现刘谦春晚魔术很好,改成了delphi版的. 1 program Project1; 2 3 {$APPTYPE CONSOLE} 4 {$R *.res} 5 6 uses 7 S ...

  2. Java I/O 教程(五) BufferedOutputStream 类

    Java BufferedOutputStream Class Java BufferedOutputStream class 用于缓冲一个输出流 其内部使用缓冲区存储数据,可以更有效率的往流中写入数 ...

  3. Qt开发Activex笔记(三):C#调用Qt开发的Activex控件

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113789727 长期持续带来更多项目与技术分享 ...

  4. 通过 saltstack 批量更新 SSL 证书

    哈喽大家好,我是咸鱼. 之前写过两篇关于 SSL 过期巡检脚本的文章: SSL 证书过期巡检脚本 SSL 证书过期巡检脚本(Python 版) 这两篇文章都是讲如何通过脚本去自动检测 SSL 过期时间 ...

  5. 类型注解Callable

    from collections.abc import Callable """ Callable[[ParamType1, ParamType2], ReturnTyp ...

  6. Linux Cheat Sheet

  7. 答对这 9 题你就超越了 83.3% 的图数据库 NebulaGraph 用户

    熟悉 NebulaGraph 社区的小伙伴可能都知道一个技能认证叫做:NGCP,全称 NebulaGraph Certified Professional.用户在考试认证期间在 1 个小时内回答 10 ...

  8. 标准差为什么除以n-1

    参考:https://blog.csdn.net/qian2213762498/article/details/80558018 如果要测量中国人的平均身高,假设为μ,通常会随机取假设10000人,求 ...

  9. 闭关修炼180天----手写迷你版的tomcat-Minicat

    手写迷你版的tomcat-Minicat 小谈Tomcat Tomcat请求处理⼤致过程 Tomcat是⼀个Http服务器(能够接收并且处理http请求,所以tomcat是⼀个http服务器) 我们使 ...

  10. Linux性能监控(二)-top

    top命令可以用来监控服务器CPU.内存的运行情况,是Linux一个经常使用到的命令. 基本用法 第一行 显示当前系统运行信息,系统当前时间是23:23:21,运行了315days,当前有2个用户登录 ...