兩張超級大表join優化

2022-09-12 10:27:19 字數 3407 閱讀 1454

乙個簡單的兩表關聯,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;

commit;

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的處理方式

兩張超級大表join優化 乙個簡單的兩表關聯,sql跑了差不多一天一夜,這兩個表都非常巨大,每個表都有幾十個g,資料量每個表有20多億,表的字段也特別多。相信大家也知道sql慢在 了,單個程序的pga 是絕對放不下幾十個g的資料,這就會導致消耗大量temp tablespace,sql慢就是慢在te...

hive大表join空key優化

假如不需要id為null的資料!此時可以將a表中id為null的字段提前過濾,減少mr在執行時,輸入的資料量!解決 將null值過濾,過濾後再執行join select from a where c is not null a left join b on a.c b.ca表中c欄位為null的資料...

hive兩大表關聯優化試驗

呼叫結果 call result 與銷售歷史 sale history 的join優化 call result 32億條 444g sale history 17億條 439g 總體來看,效果都不明顯 hive預設使用reduce side join,當兩個表中有乙個較小的時候可以考慮map joi...