PostgreSQL中的partition-wise join
与基于继承的分区(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的更多相关文章
- Oracle中的三种Join 方式
基本概念 Nested loop join: Outer table中的每一行与inner table中的相应记录join,类似一个嵌套的循环. Sort merge join: 将两个表排序,然后再 ...
- Oracle Partition Outer Join 稠化报表
partition outer join实现将稀疏数据转为稠密数据,举例: with t as (select deptno, job, sum(sal) sum_sal from emp group ...
- 通过arcgis在PostgreSQL中创建企业级地理数据库
部署环境: Win7 64位旗舰版 软件版本: PostgreSQL-9.1.3-2-windows-x64 Postgis-pg91x64-setup-2.0.6-1 Arcgis 10.1 SP1 ...
- PostgreSQL 中日期类型转换与变量使用及相关问题
PostgreSQL中日期类型与字符串类型的转换方法 示例如下: postgres=# select current_date; date ------------ 2015-08-31 (1 row ...
- PostgreSQL 中定义自己需要的数据类型
PostgreSQL解决某系数据库中的tinyint数据类型问题,创建自己需要的数据类型如下: CREATE DOMAIN tinyint AS smallint CONSTRAINT tinyint ...
- 在PostgreSQL中使用oracle_fdw访问Oracle
本文讲述如何在PostgreSQL中使用oracle_fdw访问Oracle上的数据. 1. 安装oracle_fdw 可以参照:oracle_fdw in github 编译安装oracle_fdw ...
- [原创]PostgreSQL中十进制、二进制、十六进制之间的相互转换
在PostgreSQL中,二进制.十进制.十六进制之间的转换是非常方便的,如下: 十进制转十六进制和二进制 mydb=# SELECT to_hex(10); to_hex -------- a (1 ...
- (转)MapReduce中的两表join几种方案简介
转自:http://blog.csdn.net/leoleocmm/article/details/8602081 1. 概述 在传统数据库(如:MYSQL)中,JOIN操作是非常常见且非常耗时的.而 ...
- 用python随机生成数据,再插入到postgresql中
用python随机生成学生姓名,三科成绩和班级数据,再插入到postgresql中. 模块用psycopg2 random import random import psycopg2 fname=[' ...
随机推荐
- springboot自定义CORS&XSS拦截器
springboot 项目前后端接口,防止xss攻击以及跨域问题解决 1.启动类添加注解 @ServletComponentScan 2.cors的拦截类 package com.longfor.hr ...
- ssm的maven项目启动tomcat时报错,Cannot find class: XXXX解决办法
最近在写一个ssm的项目,启动总是报错.原因网上查了也没找到.最后终于解决.下面直接上代码 问题描述: 严重: Allocate exception for servlet ssm-dispatche ...
- 详解Linux获取启动盘路径命令--fdisk、sfdisk -l、lsblk
概述 linux引导磁盘路径可以用于任何问题的故障诊断.这个引导分区或路径包含GRUB配置的Linux引导装载程序.那么我们可以怎么找到当前Linux引导磁盘路径呢? 基本上有三种方法可以找到当前Li ...
- VLAN实验4:利用单臂路由实现VLAN间路由
单臂路由: 实验环境: 实验拓扑图: 实验编址: 实验步骤:1.创建VLAN并配置Access.Trunk接口. 我们在S2上创建VLAN10和VLAN20,并且吧链接PC1的E0/0/1和链接PC2 ...
- Linux操作系统故障排除之Grub信息被删除
Linux操作系统故障排除之Grub信息被删除 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. [root@yinzhengjie ~]# hexdump -C /dev/sda - ...
- ITIL 4Foundation认证
2019年5月参加了ITIL 4Foundation培训和认证.最新的ITIL4版本中,结合了Lean.Agile和DevOps的思想.经过学习后,在思想上有很大的收货. 在此记录自己的成长.
- Python+Selenium+Appium对APP进行UI自动化测试
1. 安装Python3.7版本 pythonjava的JDK java -version javac nodejs node --versionappium 若nodejs安装完毕,使用npm安装a ...
- 小白式Git使用教程,从0到1
Git是什么? Git是目前世界上最先进的分布式版本控制系统.工作原理 / 流程: Workspace:工作区 Index / Stage:暂存区 Repository:仓库区(或本地仓库) Remo ...
- Python通过xpath查找元素通过selenium读取元素信息
#coding:utf-8 from selenium import webdriver import time url ='http://www.baidu.com' driver = webdri ...
- Java 14 周作业
题目:编写一个应用程序,输入一个目录和一个文件类型,显示该目录下符合该类型的所有文件.之后,将这些文件中的某一个文件剪切到另外一个目录中. 代码: package ccut.cn; import ja ...