与基于继承的分区(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. Linux-firewall防火墙

    systemctl status firewalld firewall-cmd --zone=public --list-ports ##查看已开放的端口 2.添加5901端口到白名单 执行 fire ...

  2. CSS制作华为mate8手机模型示例

    CSS制作华为mate8手机模型效果图 1.HTML代码 <!DOCTYPE html> <html> <head> <meta charset=" ...

  3. 在markdown中插入github仓库中的图片

    右击github中的图片,获得链接: https://github.com/nxf75/ML_Library/blob/master/Hadoop/Haddop%E6%A1%86%E6%9E%B6.p ...

  4. 账户(/etc/passwd、/etc/shadow)与组(/etc/group、/etc/gshadow)文件解析

    1. 账户信息文件 账户信息被保存在 /etc/passwd 文件中,通过命令 cat /etc/passwd 查看文件内容如下: [root@192 ~]# cat /etc/passwdroot: ...

  5. JS数组扁平化(flat)

    需求:多维数组=>一维数组 let ary = [1, [2, [3, [4, 5]]], 6]; let str = JSON.stringify(ary); 第0种处理:直接的调用 arr_ ...

  6. vue 中 axios 使用

    前言 在对接接口的时候时常会有传参问题调调试试很多,是 JSON.From Data还是 URL 传参,没有搞清楚就浪费很多时间. 本文中就结合 axios 来说明这些的区别,以便在以后工作更好对接. ...

  7. 项目Alpha冲刺--6/10

    项目Alpha冲刺--6/10 作业要求 这个作业属于哪个课程 软件工程1916-W(福州大学) 这个作业要求在哪里 项目Alpha冲刺 团队名称 基于云的胜利冲锋队 项目名称 云评:高校学生成绩综合 ...

  8. Json在序列化注意问题

    Java中的Json序列化,不容忽视的getter 问题重现 public class AjaxJson { private boolean success; private String msg; ...

  9. 数据分析 - Numpy

    简介 Numpy是高性能科学计算和数据分析的基础包.它也是pandas等其他数据分析的工具的基础,基本所有数据分析的包都用过它.NumPy为Python带来了真正的多维数组功能,并且提供了丰富的函数库 ...

  10. KMP + BZOJ 4974 [Lydsy1708月赛]字符串大师

    KMP 重点:失配nxtnxtnxt数组 意义:nxt[i]nxt[i]nxt[i]表示在[0,i−1][0,i-1][0,i−1]内最长相同前后缀的长度 图示: 此时nxt[i]=jnxt[i]=j ...