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=[' ...
随机推荐
- scrapy随机切换user-agent
使用github的 scrapy-fake-useragent 不用自己改源码继承自带的userAgent中间件 只需要安装后增加配置即可 https://github.com/alecxe/scr ...
- Spring 重定向(Redirect)指南
原文:Hacking the IntegerCache in Java 9? 链接:https://dzone.com/articles/hacking-the-integercache-in-jav ...
- prometheus-redis-exporter监控redis
chart地址:https://github.com/helm/charts/tree/master/stable/prometheus-redis-exporter 1.下载chart包 $ hel ...
- c#在WinForm和WebForm中根据控件和属性名获取控件属性值
在WinForm中开发的过程中,所有继承了Control控件,在使用多线程的时候,就需要通过一个通用的方法来设置界面上的控件的属性. delegate void DelegateSetControl( ...
- Python爬虫入门——使用requests爬取python岗位招聘数据
爬虫目的 使用requests库和BeautifulSoup4库来爬取拉勾网Python相关岗位数据 爬虫工具 使用Requests库发送http请求,然后用BeautifulSoup库解析HTML文 ...
- python开发笔记-变长字典Series的使用
Series的基本特征: 1.类似一维数组的对象 2.由数据和索引组成 import pandas as pd >>> aSer=pd.Series([1,2.0,'a']) > ...
- Ranger安装部署 - solr安装
1. 概述 Lucene是一个Java语言编写的利用倒排原理实现的文本检索类库: Solr是以Lucene为基础实现的文本检索应用服务.Solr部署方式有单机方式.多机Master-Slaver方法. ...
- Linux——配置maven
前言 Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(De ...
- 给jenkins更换工作空间
如果使用jenkins的默认工作空间,它默认安放在 /var/lib/jenkins 目录下,但这个在分配Linux磁盘的时候,一般为40G,时间长或者项目多的话,很容易将磁盘空间占满,所以我们需要将 ...
- Spring之IOC(控制反转)与AOP(面向切面编程)
控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合.当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象.可以认为IoC与JND ...