一个简单的两表关联,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

两张超级大表join优化的更多相关文章

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

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

  2. 一次MySQL两千万数据大表的优化过程,三种解决方案

    问题概述 使用阿里云rds for MySQL数据库(就是MySQL5.6版本),有个用户上网记录表6个月的数据量近2000万,保留最近一年的数据量达到4000万,查询速度极慢,日常卡死.严重影响业务 ...

  3. Hive优化-大表join大表优化

    Hive优化-大表join大表优化 5.大表join大表优化 如果Hive优化实战2中mapjoin中小表dim_seller很大呢?比如超过了1GB大小?这种就是大表join大表的问题.首先引入一个 ...

  4. cmds系统数据库源端大表数据更新优化

    cmds系统数据库源端大表数据更新优化 以下脚本可以用于将表按照rowid范围分区,获得指定数目的rowid Extent区间(Group sets of rows in the table into ...

  5. hive两大表关联优化试验

    呼叫结果(call_result)与销售历史(sale_history)的join优化: CALL_RESULT: 32亿条/444G SALE_HISTORY:17亿条/439G 原逻辑 Map: ...

  6. 【Spark调优】大表join大表,少数key导致数据倾斜解决方案

    [使用场景] 两个RDD进行join的时候,如果数据量都比较大,那么此时可以sample看下两个RDD中的key分布情况.如果出现数据倾斜,是因为其中某一个RDD中的少数几个key的数据量过大,而另一 ...

  7. 1.多表查询 => 转化为一张联合大表 2.可视化工具 3.pymysql模块

    多表数据 create table dep( id int primary key auto_increment, name varchar(16), work varchar(16) ); crea ...

  8. mysql大表如何优化

    作者:哈哈链接:http://www.zhihu.com/question/19719997/answer/81930332来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处 ...

  9. php数据库两个关联大表的大数组分页处理,防止内存溢出

    $ret = self::$db->select($tables, $fields, $where, $bind); if (!empty($ret)) { $retIds = array(); ...

随机推荐

  1. 《Effective C++》结语

    九月的这三周把<Effective C++>重读了一遍,尽量以自己的理解,用最简单的(其实太深入也不会写)的语言把书里面的重点都写了下来. 由于之前找实习占用了大量的时间,写的博客都比较水 ...

  2. 前端学习之三——jquery选择器

    Jquery中的选择器分为几大类:基本过滤选择器,层次选择器,内容过滤选择器,可见性过滤选择器,属性过滤选择器,子元素过滤选择器,表单对象选择器和表单对象属相过滤选择器. 1.非基本过滤选择器,一般需 ...

  3. [python]python中**是什么

    作为运算符时 ** 在python里面表示幂运算 传递实参和定义形参(所谓实参就是调用函数时传入的参数,形参则是定义函数是定义的参数)的时候,你还可以使用两个特殊的语法:``*`` ** . 调用函数 ...

  4. Java Optional orElse() 和 orElseGet() Optional.flatMap()和Optional.map()区别

    Java Optional 的 orElse() 和 orElseGet() 的区别 1. 接收的参数不同 orElse()方法以一个自定义类型的数据作为参数 public T orElse(T t) ...

  5. Python学习笔记:类

    类可以将数据与函数封装起来,用一个例子解释,先定义一个类: class athlete: def __init__(self,a_name,a_dob=None,a_times=[]): self.n ...

  6. 【转】C++友元

    转自:https://www.cnblogs.com/BeyondAnyTime/archive/2012/06/04/2535305.html 1.友元函数的简单介绍 1.1为什么要使用友元函数 在 ...

  7. ControlTemplate in WPF ——ScrollBar

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x ...

  8. django 如何传递id 参数

    urls.py  注意这里的bid

  9. nginx子配置文件实例

    [root@bogon conf.d]# cat /etc/nginx/conf.d/test6.conf server { listen 8085; server_name 192.168.0.20 ...

  10. LeetCode.922-按奇偶排序数组 II(Sort Array By Parity II)

    这是悦乐书的第354次更新,第379篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第216题(顺位题号是922).给定非负整数的数组A,A中的一半整数是奇数,而剩下的一半 ...