20亿与20亿表关联优化方法(超级大表与超级大表join优化方法)

记得5年前遇到一个SQL。就是一个简单的两表关联。SQL跑了几乎相同一天一夜,这两个表都非常巨大。每一个表都有几十个G。数据量每一个表有20多亿,表的字段也特别多。

相信大家也知道SQL慢在哪里了,单个进程的PGA 是绝对放不下几十个G的数据,这就会导致消耗大量temp tablespace,SQL慢就是慢在temp来回来回来回...的读写数据。

遇到这样的超级大表与超级大表怎么优化呢?这篇文章将告诉你答案。

首先创建2个測试表 t1,t2 数据来自dba_objects

create table t1 as select * from dba_objects;

create table t2 as select * from dba_objects;

我们如果 t1 和 t2 就是 两个超级大表, 要执行的 SQL:   select * from t1,t2 where t1.object_id=t2.object_id;

如果t1 t2 都是几十个GB 或者更大。 那么你懂的。上面的SQL基本上是跑不出结果的。

有些人在想,开个并行不就得了,用并行 hash hash 算法跑SQL,事实上是不能够的。原因不多说了。

我们能够利用MPP数据库架构(Greenplum/Teradata/vertica)思想。或者是利用HADOOP的思想来对上面的SQL进行优化。

MPP架构/HADOOP架构的非常重要的思想就是把数据分割。把大的数据分割为非常多份小的数据。然后再对小的进行关联。那速度自然就快了。

在Oracle里面怎么把大数据切成小数据呢。有两个办法,一个是分区。另外一个是分表。我这里选择的是分区,当然了看了这篇文章你也能够分表。

创建一个表P1。在T1的表结构基础上多加一个字段HASH_VALUE,而且依据HASH_VALUE进行LIST分区

CREATE TABLE P1(
HASH_VALUE NUMBER,
OWNER VARCHAR2(30),
OBJECT_NAME VARCHAR2(128),
SUBOBJECT_NAME VARCHAR2(30),
OBJECT_ID NUMBER,
DATA_OBJECT_ID NUMBER,
OBJECT_TYPE VARCHAR2(19),
CREATED DATE,
LAST_DDL_TIME DATE,
TIMESTAMP VARCHAR2(19),
STATUS VARCHAR2(7),
TEMPORARY VARCHAR2(1),
GENERATED VARCHAR2(1),
SECONDARY VARCHAR2(1),
NAMESPACE NUMBER,
EDITION_NAME VARCHAR2(30)
)  
   PARTITION BY  list(HASH_VALUE)
(
partition p0 values (0),
partition p1 values (1),
partition p2 values (2),
partition p3 values (3),
partition p4 values (4)
)

相同的。在T2的表结构基础上多加一个字段HASH_VALUE。而且依据HASH_VALUE进行LIST分区

CREATE TABLE P2(
HASH_VALUE NUMBER,
OWNER VARCHAR2(30),
OBJECT_NAME VARCHAR2(128),
SUBOBJECT_NAME VARCHAR2(30),
OBJECT_ID NUMBER,
DATA_OBJECT_ID NUMBER,
OBJECT_TYPE VARCHAR2(19),
CREATED DATE,
LAST_DDL_TIME DATE,
TIMESTAMP VARCHAR2(19),
STATUS VARCHAR2(7),
TEMPORARY VARCHAR2(1),
GENERATED VARCHAR2(1),
SECONDARY VARCHAR2(1),
NAMESPACE NUMBER,
EDITION_NAME VARCHAR2(30)
)  
   PARTITION BY  list(HASH_VALUE)
(
partition p0 values (0),
partition p1 values (1),
partition p2 values (2),
partition p3 values (3),
partition p4 values (4)
)

注意:P1和P2表的分区必须一模一样

delete t1 where object_id is null;

commit;

delete t1 where object_id is null;

commit;

insert into p1
select ora_hash(object_id,4), a.*  from t1 a;  ---工作中用append parallel并行插入

commit;

insert into p2
select ora_hash(object_id,4), a.*  from t2 a;  ---工作中用append parallel并行插入

commit;

这样就把 T1 和 T2的表的数据转移到 P1 和 P2 表中了

那么之前执行的 select * from t1,t2 where t1.object_id=t2.object_id  事实上就等价于以下5个SQL了

select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=0 and p2.hash_value=0;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=1 and p2.hash_value=1;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=2 and p2.hash_value=2;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=3 and p2.hash_value=3;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=4 and p2.hash_value=4;

工作中。大表拆分为多少个分区,请自己推断。

另外一个须要注意的就是ORA_HASH函数

oracle中的hash分区就是利用的ora_hash函数

partition by hash(object_id) 等价于 ora_hash(object_id,4294967295)

ora_hash(列,hash桶) hash桶默认是4294967295 能够设置0到4294967295

ora_hash(object_id,4) 会把object_id的值进行hash运算,然后放到 0,1,2,3,4 这些桶里面,也就是说 ora_hash(object_id,4) 仅仅会产生 0 1 2 3 4

有兴趣的同学能够自己去測试速度。

生产库採用这样的优化方法,之前须要跑一天一夜的SQL。在1小时内完毕。

为了简便,能够使用PLSQL编写存储过程封装上面操作。

当然了,如果使用hadoop 或者 greenplum 有另外的优化方法这里就不做介绍了。

道森出品必属精品 抄袭翻版必究

??

时间: 2024-08-02 07:01:44

20亿与20亿表关联优化方法(超级大表与超级大表join优化方法)的相关文章

MySQL表关联的几种常用方式

工作中我们经常会使用表与表关联来查询数据,如果对join 不熟悉,可能会得到我们不想要的节过,这里就来介绍下join的几种常用方法:建表及插入数据,CREATE TABLE school (sch_id int(11) NOT NULL AUTO_INCREMENT,sch_name varchar(50) NOT NULL,sch_addr varchar(100) DEFAULT NULL,PRIMARY KEY (sch_id)) ENGINE=InnoDB AUTO_INCREMENT=

图解SQL多表关联查询

图解SQL多表关联查询 网上看了篇文章关于多表连接的,感觉很好,记录下来,以便日后自己学习  内连接 左连接 右连接 全外连接

Oracle 数据库(oracle Database)Select 多表关联查询方式

Oracle数据库中Select语句语法及介绍 SELECT [ ALL | DISTINCT ] <字段表达式1[,<字段表达式2[,…] FROM <表名1>,<表名2>[,…] [WHERE <筛选择条件表达式>] [GROUP BY <分组表达式> [HAVING<分组条件表达式>]] [ORDER BY <字段>[ASC | DESC]] 语句说明: []方括号为可选项 [GROUP BY <分组表达式&g

Mysql 查询技巧:使用JOIN优化子查询

1.数据准备 mysql> select * from student; +----+--------+----------+---------+-------------+ | id | name   | idCardNo | isCadre | nickname    | +----+--------+----------+---------+-------------+ |  1 | Tom    | 350020   |       1 | Big T       | |  2 | Ji

【面试被虐】如何只用2GB内存从20亿,40亿,80亿个整数中找到出现次数最多的数?

这几天小秋去面试了,不过最近小秋学习了不少和位算法相关文章,例如 [面试现场]如何判断一个数是否在40亿个整数中? [算法技巧]位运算装逼指南 对于算法题还是有点信心的,,,,于是,发现了如下对话. 20亿级别 面试官:如果我给你 2GB 的内存,并且给你 20 亿个 int 型整数,让你来找出次数出现最多的数,你会怎么做? 小秋:(嗯?怎么感觉和之前的那道判断一个数是否出现在这 40 亿个整数中有点一样?可是,如果还是采用 bitmap 算法的话,好像无法统计一个数出现的次数,只能判断一个数是

mark---[mysql多表关联查询的优化方法]

对于一个网站来说,数据库的结构至关重要.即要利于存储(入库不阻塞),又要利于查询(查询不锁表).网站数据库优化经验是一个积累的过程.下面就对多表关联查询的优化方法,举例说明. 现在社区分享类网站很火,就拿方维购物分享网站举例说明吧.也是对二次开发方维购物分享网站的一点总结,高手可以飞过. 购物分享的关键表有:分享表.图片表.文件表.评论表.标签表.分类表等. 围绕分享的表就么多,哇,那也不少啊.当我们查看一个图片的详细信息时,就要显示以上表里的信息.显示图片所属的分类.给图片打的标签.图片的评论

Hive中小表与大表关联(join)的性能分析【转】

Hive中小表与大表关联(join)的性能分析 [转自:http://blog.sina.com.cn/s/blog_6ff05a2c01016j7n.html] 经常看到一些Hive优化的建议中说当小表与大表做关联时,把小表写在前面,这样可以使Hive的关联速度更快,提到的原因都是说因为小表可以先放到内存中,然后大表的每条记录再去内存中检测,最终完成关联查询.这样的原因看似合理,但是仔细推敲,又站不住脚跟. 多小的表算小表?如果所谓的小表在内存中放不下怎么办?我用2个只有几条记录的表做关联查询

PostgreSQL使用函数的多表关联视图在排序时的性能问题

一.问题描述 近日PostgreSQL的某个表的记录数由万级增加到一百万级(设计能力是一亿)时,建立在该表之上的某个多表关联VIEW的查询性能急剧变慢(大约从10ms级跃升到100s级).经分析查询计划,发现瓶颈在于排序用时很长:而排序用时的诱因是什么?在排除掉一个个其它因素后,发现是VIEW定义中使用了函数(非内部函数,特此说明).在将自定义函数更改为等效的子查询或连接查询时,性能得到很好的改善. 因为实际的表.VIEW.函数都过于复杂,为描述及重现问题的关键,以下将表.VIEW.函数等都进行

yii2 ActiveRecord多表关联以及多表关联搜索的实现

一个老生常谈的问题.最近通过群里的反馈,觉得很多人还是没有去理解这个问题.今天把这个问题讲明白了,看看yii2 ActiveRecord是怎么个多表关联以及如何去优化这个关联. 场景需求: 假设我们有一张用户表user和一张用户渠道表auth,两张数据表通过user.id和auth.uid进行一对一关联.现需要在user列表展示auth表的来源渠道source,且该渠道可搜索. 首先我们先通过gii生成user和auth系列相关的model和操作.此处不做详细说明,有关gii的操作可参考gii详