与基于继承的分区(inheritance-based partitioning)不同,PostgreSQL 10中引入的声明式分区对数据如何划分没有任何影响。PostgreSQL 11的查询优化器正准备利用这种“无推理”表示。第一个提交的是partition-wise join。

什么是partition-wise join

如果连接表的分区键之间存在相等连接条件,那么两个类似分区表之间的连接可以分解为它们的匹配分区之间的连接。分区键之间的等连接意味着一个分区表的给定分区中给定行的所有连接伙伴必须在另一个分区表的相应分区中。因此,分区表之间的连接可以分解为匹配分区之间的连接。这种将分区表之间的连接分解为分区之间的连接的技术称为partition-wise join。

PostgreSQL中的partition-wise join

让我们从一个例子开始。考虑按如下方式分区的两个表:

create table prt1 (a int, b int, c varchar) partition by range(a);
create table prt1_p1 partition of prt1 for values from (0) to (5000);
create table prt1_p2 partition of prt1 for values from (5000) to (15000);
create table prt1_p3 partition of prt1 for values from (15000) to (30000); create table prt2 (a int, b int, c varchar) partition by range(b);
create table prt2_p1 partition of prt2 for values from (0) to (5000);
create table prt2_p2 partition of prt2 for values from (5000) to (15000);
create table prt2_p3 partition of prt2 for values from (15000) to (30000);

prt1_p1中一行的所有连接伙伴都来自prt2_p1。
prt1_p2中一行的所有连接伙伴都来自prt2_p2。
而prt1_p3中一行的所有连接伙伴都来自prt2_p3。
这三个组成了匹配的分区对。没有partition-wise join,这两个表之间的连接计划如下:

explain (costs off)
select * from prt1 t1, prt2 t2 where t1.a = t2.b and t1.b = 0 and t2.b between 0 and 10000;
QUERY PLAN
-------------------------------------------------------
Hash Join
Hash Cond: (t2.b = t1.a)
-> Append
-> Seq Scan on prt2_p1 t2
Filter: ((b >= 0) AND (b <= 10000))
-> Index Scan using prt2_p2_b on prt2_p2 t2_1
Index Cond: ((b >= 0) AND (b <= 10000))
-> Hash
-> Append
-> Seq Scan on prt1_p1 t1
Filter: (b = 0)
-> Seq Scan on prt1_p2 t1_1
Filter: (b = 0)
-> Seq Scan on prt1_p3 t1_2
Filter: (b = 0)
(15 rows)

partition-wise join的加入计划为相同的查询如下:

explain (costs off)
select * from prt1 t1, prt2 t2 where t1.a = t2.b and t1.b = 0 and t2.b between 0 and 10000;
QUERY PLAN ------------------------------------------------------------------------
Append
-> Hash Join
Hash Cond: (t2.b = t1.a)
-> Seq Scan on prt2_p1 t2
Filter: ((b >= 0) AND (b <= 10000))
-> Hash
-> Seq Scan on prt1_p1 t1
Filter: (b = 0)
-> Nested Loop
-> Seq Scan on prt1_p2 t1_1
Filter: (b = 0)
-> Index Scan using prt2_p2_b on prt2_p2 t2_1
Index Cond: ((b = t1_1.a) AND (b >= 0) AND (b <= 10000))
(13 rows)

这里有几点需要注意:

1.存在一个等价连接条件t1.a=t2.b,包括来自两个表的分区键。
2.在没有partition-wise join的情况下,连接将在“appending”来自任何分区表的每个分区的所有行之后执行连接。对于partition-wise join,在匹配分区之间的连接后并附加结果。当连接结果的大小明显小于叉乘的结果时,这是有利的。更有利的是,如果分区本身是外部表,即分区中的数据驻留在外部服务器上。
3.在没有partition-wise join的情况下,它使用散列连接,但是在partition-wise join的情况下,它对分区之间的每个连接使用不同的策略,为每个连接选择最佳策略。例如,prt1_p2和prt2_p2之间的连接使用带有prt2_p2_b索引扫描的嵌套循环连接作为参数化的内端,而另一个连接使用散列连接。
4.条件t2.b between 0和10000之间消除了分区prt2_p3,因此在没有partition-wise join的情况下不会被计划扫描。但是它没有注意到prt1_p3中的任何一行都没有连接伙伴,并且仍然扫描该分区。使用partition-wise join,它意识到没有匹配的分区,消除了对prt1_p3的扫描。消除整个分区是一个重大的改进,因为顺序扫描非常昂贵。

Partition-wise join优于未分区连接,因为它可以利用分区的属性,并使用更小的哈希表,这些哈希表可能完全在内存中,更快的内存排序,在外部分区情况下的连接下推,等等。

基本的Partition-wise join之外

在提交的基本版本中,当连接表具有完全相同的分区键数据类型并具有完全匹配的分区边界时,将应用该技术。但有几个增强的可能性:

1.即使分区边界不完全匹配,当一个分区表中的每个分区最多有一个与另一个分区表匹配的分区时,也可以使用该技术。目前正在为此开发一个补丁。
2.通过将未分区表与每个分区分别连接并合并这些连接的结果,可以使用此技术执行未分区表和已分区表之间的连接。当查询中的一些表是未分区的,而其他表是类似分区的,并且一个最佳计划将分区表和未分区表交错时,这可能会有所帮助。
3.这种技术使用更多的内存和CPU,即使partition-wise join不是最佳策略。减少这种技术的内存和CPU占用。
4.当连接两个不同分区的表时,对其中一个表重新分区以匹配另一个表的分区方案,然后使用partition-wise join进行连接;一种通常有助于通过重新分布数据来连接不同的切分表的技术。

PostgreSQL中的partition-wise join的更多相关文章

  1. Oracle中的三种Join 方式

    基本概念 Nested loop join: Outer table中的每一行与inner table中的相应记录join,类似一个嵌套的循环. Sort merge join: 将两个表排序,然后再 ...

  2. Oracle Partition Outer Join 稠化报表

    partition outer join实现将稀疏数据转为稠密数据,举例: with t as (select deptno, job, sum(sal) sum_sal from emp group ...

  3. 通过arcgis在PostgreSQL中创建企业级地理数据库

    部署环境: Win7 64位旗舰版 软件版本: PostgreSQL-9.1.3-2-windows-x64 Postgis-pg91x64-setup-2.0.6-1 Arcgis 10.1 SP1 ...

  4. PostgreSQL 中日期类型转换与变量使用及相关问题

    PostgreSQL中日期类型与字符串类型的转换方法 示例如下: postgres=# select current_date; date ------------ 2015-08-31 (1 row ...

  5. PostgreSQL 中定义自己需要的数据类型

    PostgreSQL解决某系数据库中的tinyint数据类型问题,创建自己需要的数据类型如下: CREATE DOMAIN tinyint AS smallint CONSTRAINT tinyint ...

  6. 在PostgreSQL中使用oracle_fdw访问Oracle

    本文讲述如何在PostgreSQL中使用oracle_fdw访问Oracle上的数据. 1. 安装oracle_fdw 可以参照:oracle_fdw in github 编译安装oracle_fdw ...

  7. [原创]PostgreSQL中十进制、二进制、十六进制之间的相互转换

    在PostgreSQL中,二进制.十进制.十六进制之间的转换是非常方便的,如下: 十进制转十六进制和二进制 mydb=# SELECT to_hex(10); to_hex -------- a (1 ...

  8. (转)MapReduce中的两表join几种方案简介

    转自:http://blog.csdn.net/leoleocmm/article/details/8602081 1. 概述 在传统数据库(如:MYSQL)中,JOIN操作是非常常见且非常耗时的.而 ...

  9. 用python随机生成数据,再插入到postgresql中

    用python随机生成学生姓名,三科成绩和班级数据,再插入到postgresql中. 模块用psycopg2 random import random import psycopg2 fname=[' ...

随机推荐

  1. Node: Process模块 (Features of Process)

    Process模块 (Features of Process) process is a global variable which indicates the current Node.js pro ...

  2. ubifs使用方法

    常用命令: 查看块设备分区信息cat /proc/mtd 查看块设备信息mtdinfo /dev/mtd0 格式化mtd分区ubiformat /dev/mtd0 将mtd分区与ubi关联ubiatt ...

  3. 18.centos7基础学习与积累-004-分区理论

    1.从头开始积累centos7系统运用 大牛博客:https://blog.51cto.com/yangrong/p5 1.常规分区:数据不是特别重要的业务(集群的某个节点) /boot  引导分区 ...

  4. C语言开发具有可变长参数的函数的方法

    学习交流可加 微信读者交流①群 (添加微信:coderAllen) 程序员技术QQ交流①群:736386324 --- 前提:ANSI C 为了提高可移植性, 通过头文件stdarg.h提供了一组方便 ...

  5. background-image:url为空引发的两次请求问题

    参考文章: https://blog.csdn.net/jsjhushilei/article/details/51101014 1.Nicholas 在 2009 年就开始推动各浏览器厂商,现在看起 ...

  6. Map遍历效率比较

    1.由来 上次博客提到了Map的四种遍历方法,其中有的只是获取了key值或者是value值,但我们应该在什么时刻选择什么样的遍历方式呢,必须通过实践的比较才能看到效率. 也看了很多文章,大家建议使用e ...

  7. 4、markdown基本语法

    一.前言 由于有些语法无法在博客园展示,推荐使用Typora解锁全套,下载地址:https://www.typora.io/ 推荐使用jupyter,使用方法:https://www.cnblogs. ...

  8. WinDbg常用命令系列---.cmdtree

    .cmdtree 简介 使用形式 .cmdtree cmdfile 参数 cmdfile命令文件,包含多个你需要的命令.必须是一个文本档 使用步骤 1.使用命令创建文本文件test.wl,使用以下示例 ...

  9. cube.js 最近版本的一些更新

    有一段时间没有关注cube.js 了,刚好晚上收到一封来自官方的更新介绍,这里简单说明下 更多的数据驱动支持 bigquey, clickhouse snowflake,presto (很棒),hiv ...

  10. sqler 集成 terraform v0.12 生成资源部署文件

    terraform v0.12 发布了,有好多新功能的添加,包括语法的增强,新函数的引入,更好的开发提示 只是当前对于一些老版本的provider 暂时还不兼容,但是大部分官方的provider 都是 ...