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