基於MPP架構的TERADATA技術預覽
阿新 • • 發佈:2019-02-01
/***************************************/
目錄:
第一部分:Teradata架構
第二部分:常見問題,及解決方法
第三部分:Teradata工具實用小技巧
第四部分:JOIN的實現機制
第五部分:JOIN的優化
/***************************************/
第一部分:Teradata架構
1.相關概念
SMP (Symmetrical Multi-Processing)對稱多處理
MPP (Massively Parallel Processing)大規模並行處理系統
PE
MPL
AMP
VDISK
PI
UPI
NUPI
PPI
2.Teradata 體系架構
(1)資料存取架構圖-資料儲存
步驟:
Parsing Engine分發需要寫入的記錄.
Message Passing Layer確定應管理記錄的AMP
AMP將記錄寫入磁碟一個AMP管理一個邏輯儲存單元
virtual disk (它對應多個物理的儲存單元)
(2)Teradata資料存取架構圖-資料讀取
步驟:
Parsing Engine將資料讀取請求傳送到處理單元
Message Passing Layer確定要讀取的記錄屬於哪個AMP管理
AMP(s)定位要讀取的記錄的儲存位置並讀取.
Message Passing Layer將結果記錄反饋到PE
PE將結果記錄反饋到請求端.
(3)均勻的資料分佈
Notes:
每個表中的記錄都會比較均勻地分佈到各個AMP中.
每個AMP中的都會儲存系統中幾乎所有表的資料.
(4)完全線性擴充套件性
(5)Primary Index 主索引
利用PI訪問資料的特點:
總是使用一個AMP
高效率的記錄訪問方式
(6)Primary Index 主索引資料訪問
UPI 訪問一個AMP,讀取一條記錄
NUPI 訪問一個AMP,讀取多條記錄
(7)資料分佈 1(UPI)
資料分佈 2(NUPI)
(8)PI的選取
重複值越少越好
個數越少越好
越經常使用越好
少更新
建表時要指定
(9)PPI 例子
第二部分:常見問題,及解決方法
1.常見問題分類:
表屬性不對: Set / Multiset
問題:INSERT操作慢
主索引(PI)設定不合理
問題1:資料傾斜度大,空間爆滿。
問題2:JOIN操作,資料需要重分佈。
分割槽索引(PPI)設定不合理
問題:全表掃描
連線條件過於複雜
問題:系統無法優化執行計劃
缺乏統計資訊
問題:系統無法找到最優化的執行計劃
2.表屬性:Set & MultiSet
Set Table不允許記錄重複
MultiSet Table允許記錄重複
預設值:Set Table
Create Table... AS ... 生成的目標表屬性預設為Set Table
對SET Table進行INSERT操作,需要檢查是否存在重複記錄
相當的耗資源
若真要限定唯一性,可以通過UPI或USI實現
3.PI(Primary Index 主索引)的選擇
PI影響資料的儲存與訪問,其選擇標準:
不同值儘量多的欄位(More Unique Values)
使用頻繁的欄位:包括值訪問和連線訪問
少更新
PI欄位不宜太多
最好是手動指定PI
4.PPI的使用
PPI(Partition Primary Index,分割槽索引),把具有相同分割槽值的資料聚簇存放在一起;
類似於SQL Server的聚簇索引(Cluster Index),Oracle的聚簇表(Cluster Table)。
利用PPI,可以快速插入/訪問同一個Partition(分割槽)的資料。
5.建立可變臨時表
它僅存活於同一個Session之內
注意指定可變臨時表為multiset(通常也要指定PI)
可變臨時表不能帶有PPI
6.固化臨時表
固化臨時表,就是把查詢結果存放到一張物理表。
共下次分析或他人使用
Session斷開之後,仍然可以使用。
7.資料型別
注意非日期欄位與日期欄位char & date的轉換與關聯:
如果資料型別一致可以直接使用;
在CASE WHEN or COALESCE一定要使用顯式的型別轉換(CAST)
CASE WHEN A = B THEN DATE1 ELSE ‘20061031’ END
應寫成CASE WHEN A = B THEN DATE1 ELSE CAST(‘20061031’ AS DATE) END
數值運算時,確保運算過程中不丟失計算精度。
CAST(100/3 AS DEC(5,2))應該寫成CAST(100/3.00 AS DEC(5,2))
8.字元(串)與數字相比較
比較規則:
1) 比較兩個值(欄位),它們的型別必須一樣!
2) 當字元(串)與數字相比較時,先把字元(串)轉換成數字,再進行比較。
9.目標列的選擇
減少目標列,可以少消耗SPOOL空間,從而提高SQL的效率
當系統任務繁忙,系統記憶體少的時候,效果尤為明顯。
10.Where條件的限定
根據Where條件先進行過濾資料集,再進行連線(JOIN)等操作
這樣,可以減少參與連線操作的資料集大小,從而提高效率
好的查詢引擎,可以自動優化;但有些複雜SQL,查詢引擎優化得並不好。
注意:系統的SQL優化,只是避免最差的,選擇相對優的,未必能夠得到最好的優化結果。
11.用Case When替代UNION
兩個子查詢的表連線部分完全一樣
兩個子查詢除了取資料條件,其它都一樣。
Union all是多餘的,它需要重複掃描資料,進行重複的JOIN
可以用Case when替代union
12.用OR替代UNION
兩個子查詢的表連線部分完全一樣
兩個子查詢除了取資料條件,其它都一樣。
Union all是多餘的,它需要重複掃描資料,進行重複的JOIN
可以用OR替代union
此類的問題,在指令碼中經常見到。
13.Union和Union all
Union與Union all的作用是將多個SQL的結果進行合併。
Union將自動剔除集合操作中的重複記錄;需要耗更多資源。
Union all則保留重複記錄,一般建議使用Union all。
第一個SELECT語句,決定輸出的欄位名稱,標題,格式等
要求所有的SELECT語句:
1) 必須要有同樣多的表示式數目;
2) 相關表示式的域必須相容
14.先Group by再join
記錄數情況:t: 580萬,b: 9400萬, c:8, d:8
主要問題:假如連線順序為:( (b join c) join d) join t)
則是( (9400萬 join 8) join 8) join 580萬)
資料分佈時間長(IO多),連線次數多
解決方法:先執行(t join b),然後groupby,再join c,d
結果:
(1) VTDUR_MON join VTNEW_SUBS_THISYEAR
PI相同,merge join,只需10秒
(2)經過group by,b表只有332記錄
(3)b join c join d, 就是:
332 × 8 × 8
(4)最終結果:5記錄,共40秒
先彙總再連線,可以減少參與連線的資料集大小,減少比較次數,從而提高效率。
以下面SQL為例,假設歷史表( History )有1億條記錄
左邊的SQL,需要進行 1億 × 90次比較
右邊的SQL,則只需要 1億 × 1 次比較
15.SQL書寫不當可能會引起笛卡兒積
以下面兩個SQL為例,它們將進行笛卡兒積操作。
例子1:
Select
employee.emp_no
, employee.emp_name
From employee A
表Employee與表A進行笛卡兒積
例子2:
SELECT A.EMP_Name, B.Dept_Name
FROM employee A, Department B
Where a.dept_no = b.dept_no;
表A與表B進行笛卡兒積
表A與表B進行Inner Join
16.修改表定義
常見的表定義修改操作:
增加欄位
修改欄位長度
建議的操作流程
Rename table db.tablex as db.tabley;
通過Show table語句獲得原表db.tablex的定義
定義新表: db.tablex
Insert into db.tablex(。。。)
select 。。。 From db.tabley;
Drop table db.tabley;
Teradata提供ALTER TABLE語句,可進行修改表定義
但,不建議採用ALTER TABLE方式。
17.插入/更新/刪除記錄時,儘量不要Abort
當目標表有資料時,插入和更新操作,以及部分刪除,都產生TJ
如果此時abort該操作,系統將會回滾
對於大表進行Update/DELETE操作,將耗費相當多的資源與相當長的時間。
Update/Delete操作,需要事務日誌TJ(Transient Journal)
以防意外中斷導致資料受到破壞
在Update/Delete操作中途被Cancel,系統則需回滾,這將耗更多的資源與時間!
第三部分:Teradata工具實用小技巧
1.SQL變數
SELECT DATABASE; 顯示當前資料庫
PVIEW
SELECT USER; 顯示當前Session登陸的使用者名稱
lusc
SELECT DATE, CURRENT_DATE ; 顯示當前日期
20070806 , 20070806
定義格式: SELECT CAST(DATE AS DATE FORMAT 'YYYYMMDD')
Select TIME, CURRENT_TIMESTAMP(0);顯示當前時間
18:46:35, 2007-08-06 18:46:34+00:00
轉換: SELECT CAST(CURRENT_TIMESTAMP(0) AS CHAR(19));
2007-08-06 18:47:59
2.日期(DATE)的操作
取當前天:
select cast( current_date as DATE FORMAT 'YYYYMMDD')
取當前天的前一天,後一天
select cast( current_date -1 as DATE FORMAT 'YYYYMMDD')
select cast( current_date + 1 as DATE FORMAT 'YYYYMMDD')
取前(後)一個月的同一天
Select add_months(current_date , -1)
Select add_months(current_date , 1)
若current_date為20070331,結果是什麼?
取當前天所在月的第一天
select substr(cast(current_date as date format 'YYYYMMDD'),1,6) || '01';
取當前天所在月的最後一天
select cast( substr(cast( add_months(current_date,1) as date format 'YYYYMMDD'),1,6) || '01‘ as date format 'YYYYMMDD') -1
日期相減
SELECT ( DATE '2007-03-01' - DATE '2004-01-01') day(4);
SELECT (DATE'2007-03-01'- DATE'2004-01-01') month(4) ;
3.日曆表:Sys_calendar.Calendar
用於進行復雜的日期計算
判斷日期是否合法,例如20070229
SELECT * FROM Sys_calendar.Calendar
WHERE calendar_date = cast('2007-02-29' as date format ‘yyyy-mm-dd’);
返回空值,則說明該日期是非法的。
判斷某日歸屬當月(當年)的第幾周,當年的第幾季度等
Select week_of_month, Week_of_year, quarter_of_year
From Sys_calendar.Calendar
WHERE calendar_date = cast('2006-10-15' as date format 'yyyy-mm-dd');
取當前月的天數
Select max(day_of_month)
From Sys_calendar.Calendar
WHERE cast( cast(calendar_date as date format 'yyyymmdd') as char(8)) like '200708%‘
或 where month_of_calendar in (
select month_of_calendar
From Sys_calendar.Calendar
where calendar_date = cast('2007-08-01' as date format 'yyyy-mm-dd')
)
第四部分:JOIN的實現機制
1.LEFT Outer Join 舉例
SELECT E.Last_name
,E.Department_Number
,D.Department_Name
FROM Employee E LEFT OUTER JOIN
Department D
ON E.Department_Number = D.Department_Number
Last_Name Department_Number Department_Name
Crane 402 software support
James 111 ?
Runyon 501 marketing and sales
Stein 301 research and develop
Green ? ?
Trainer 100 executive
Kanieski 301 research and develop
內連線相比,這個查詢的結果集會增加下面的一些記錄:
部門號為空的員工。
部門號不在部門程式碼表裡面的員工。
2.Join之前的重分佈
Join 的列都是兩個表的PI 不需要資料重分佈.
SELECT . . .
FROM Table1 T1
INNER JOIN Table2 T2
ON T1.A = T2.A;
Join 的列都是在一個表上是PI,另外一個表上不是PI 是PI的表不需要重分佈.
SELECT . . .
FROM Table1 T1
INNER JOIN Table2
ON T1.A = T2.A;
3.複製小表到Spool空間
4.關聯策略 Merge Join
適用情況:
兩個表的資料量都比較大時
例如 100萬 × 30萬
用來Join的記錄必須位於相同的AMP上
Merge Join 僅僅讀取每個表一次.
對於等值條件的Join,優化器經常會選用Merge Join.
通常情況下比product join的效率更高.
Merge join 處理流程:
找到一個小表.
如果需要:
將一個或者兩個表要用到的資料都放在Spool空間裡.
基於Join列的hash值將記錄重分佈到相應的AMP.
根據Join列的hash順序對spool裡面的記錄進行排序.
對於Join列的Hash值相同的記錄進行比較.
與Product Join相比,比較次數大大降低.
5.關聯策略 Product Join
適用情況:
大表非PI欄位對小表
例如 30萬 × 50
不對記錄做排序
如果記憶體裡面放不下的時候需要多次讀取某張表.
Table1 的每條記錄要與 Table2 的每條記錄進行比對.
滿足條件的記錄會被放到 spool空間中.
之所以會被稱作Product Join 是因為:
總共的比較次數 = Table 1 的記錄條數 * Table 2的記錄條數
當記憶體裡面不能存放某一個表的所有資料的時候,這種比較會變得非常的消耗資源,因為總是需要內外存的交換。
如果沒有where條件,Product Join通常會產生無意義的結果.
Product Join 處理步驟:
找到小表並在Spool空間中複製到所有AMP上.
在每個AMP上,Spool空間裡的小表的每一行和大表在該AMP上的每一行做Join
6.關聯策略 Hash Join
適用情況:
大表非PI欄位對中等小的表
例如 700萬 × 1萬
優化器技術有效的將小表放在Cache記憶體中,並且與未排序的大表進行關聯.
Row Hash Join的處理流程:
找到小表.
重分佈小表或者複製小表到各個AMP的記憶體中.
將小表在Cache記憶體中按照join欄位的 row hash順序排序.
將記錄放在記憶體中.
用大表的join欄位的row hash在記憶體中進行折半查詢.
這種join將減少大表的排序、重分佈或者拷貝.
EXPLAIN 將會看見類似於“Single Partition Hash Join”的術語.
7.多表連線
多表連線可以分解為兩兩連線.
對下面的SQL,查詢引擎可以選擇較優的執行計劃:例如,Plan1或者Plan2。
SELECT …. FROM Table_A, Table_B, Table_C, Table_D WHERE . . . ;
對下面的SQL,查詢引擎只能選擇Plan2,否則結果有可能不對。
SELECT ….
FROM Table_A left join Table_B on A.c1 = B.c2
INNER JOIN Table_C ON B.c2 = c.c3
LEFT JOIN Table_D ON D.C4 = A.C1
WHERE . . . ;
第五部分:JOIN的優化
1.改變查詢計劃的手段
修改PI
收集統計資訊
關聯欄位上的統計資訊
Partition上的統計資訊
Where條件上的統計資訊
Group by 欄位上的統計資訊
檢視某個表的統計資訊情況:help stat DBName.TableName
檢視詳盡的統計情況:select * from pview.vw_statistic_info
通過Explain檢視,尚需統計哪些資訊?
diagnostic helpstats on for session;
2.JOIN問題的經驗分析
執行速度慢的SQL,絕大多數都是JOIN
例外1:INSERT操作慢,可能是因為目標表為set型別,或者PI不對
例外2:資料讀取慢,可能用like操作,或者資料本身就很大
JOIN的問題,主要在於:
資料分佈方式不對:把大表進行duplicate,或者redistribute
大表Redistribute有可能導致資料分佈不均衡
JOIN演算法不對:
例如,大表join小表,用merge join導致大表需要重新hash與sort
例如,大表join大表不用merge join
JOIN問題的解決辦法:
對參與join的欄位進行統計資訊
必要的時候,固化臨時表,並統計資訊
一般情況下,不需要調整SQL的業務邏輯
目錄:
第一部分:Teradata架構
第二部分:常見問題,及解決方法
第三部分:Teradata工具實用小技巧
第四部分:JOIN的實現機制
第五部分:JOIN的優化
/***************************************/
第一部分:Teradata架構
1.相關概念
SMP (Symmetrical Multi-Processing)對稱多處理
MPP (Massively Parallel Processing)大規模並行處理系統
PE
MPL
AMP
VDISK
PI
UPI
NUPI
PPI
2.Teradata 體系架構
(1)資料存取架構圖-資料儲存
步驟:
Parsing Engine分發需要寫入的記錄.
Message Passing Layer確定應管理記錄的AMP
AMP將記錄寫入磁碟一個AMP管理一個邏輯儲存單元
virtual disk (它對應多個物理的儲存單元)
(2)Teradata資料存取架構圖-資料讀取
步驟:
Parsing Engine將資料讀取請求傳送到處理單元
Message Passing Layer確定要讀取的記錄屬於哪個AMP管理
AMP(s)定位要讀取的記錄的儲存位置並讀取.
Message Passing Layer將結果記錄反饋到PE
PE將結果記錄反饋到請求端.
(3)均勻的資料分佈
Notes:
每個表中的記錄都會比較均勻地分佈到各個AMP中.
每個AMP中的都會儲存系統中幾乎所有表的資料.
(4)完全線性擴充套件性
(5)Primary Index 主索引
利用PI訪問資料的特點:
總是使用一個AMP
高效率的記錄訪問方式
(6)Primary Index 主索引資料訪問
UPI 訪問一個AMP,讀取一條記錄
NUPI 訪問一個AMP,讀取多條記錄
(7)資料分佈 1(UPI)
資料分佈 2(NUPI)
(8)PI的選取
重複值越少越好
個數越少越好
越經常使用越好
少更新
建表時要指定
(9)PPI 例子
第二部分:常見問題,及解決方法
1.常見問題分類:
表屬性不對: Set / Multiset
問題:INSERT操作慢
主索引(PI)設定不合理
問題1:資料傾斜度大,空間爆滿。
問題2:JOIN操作,資料需要重分佈。
分割槽索引(PPI)設定不合理
問題:全表掃描
連線條件過於複雜
問題:系統無法優化執行計劃
缺乏統計資訊
問題:系統無法找到最優化的執行計劃
2.表屬性:Set & MultiSet
Set Table不允許記錄重複
MultiSet Table允許記錄重複
預設值:Set Table
Create Table... AS ... 生成的目標表屬性預設為Set Table
對SET Table進行INSERT操作,需要檢查是否存在重複記錄
相當的耗資源
若真要限定唯一性,可以通過UPI或USI實現
3.PI(Primary Index 主索引)的選擇
PI影響資料的儲存與訪問,其選擇標準:
不同值儘量多的欄位(More Unique Values)
使用頻繁的欄位:包括值訪問和連線訪問
少更新
PI欄位不宜太多
最好是手動指定PI
4.PPI的使用
PPI(Partition Primary Index,分割槽索引),把具有相同分割槽值的資料聚簇存放在一起;
類似於SQL Server的聚簇索引(Cluster Index),Oracle的聚簇表(Cluster Table)。
利用PPI,可以快速插入/訪問同一個Partition(分割槽)的資料。
5.建立可變臨時表
它僅存活於同一個Session之內
注意指定可變臨時表為multiset(通常也要指定PI)
可變臨時表不能帶有PPI
6.固化臨時表
固化臨時表,就是把查詢結果存放到一張物理表。
共下次分析或他人使用
Session斷開之後,仍然可以使用。
7.資料型別
注意非日期欄位與日期欄位char & date的轉換與關聯:
如果資料型別一致可以直接使用;
在CASE WHEN or COALESCE一定要使用顯式的型別轉換(CAST)
CASE WHEN A = B THEN DATE1 ELSE ‘20061031’ END
應寫成CASE WHEN A = B THEN DATE1 ELSE CAST(‘20061031’ AS DATE) END
數值運算時,確保運算過程中不丟失計算精度。
CAST(100/3 AS DEC(5,2))應該寫成CAST(100/3.00 AS DEC(5,2))
8.字元(串)與數字相比較
比較規則:
1) 比較兩個值(欄位),它們的型別必須一樣!
2) 當字元(串)與數字相比較時,先把字元(串)轉換成數字,再進行比較。
9.目標列的選擇
減少目標列,可以少消耗SPOOL空間,從而提高SQL的效率
當系統任務繁忙,系統記憶體少的時候,效果尤為明顯。
10.Where條件的限定
根據Where條件先進行過濾資料集,再進行連線(JOIN)等操作
這樣,可以減少參與連線操作的資料集大小,從而提高效率
好的查詢引擎,可以自動優化;但有些複雜SQL,查詢引擎優化得並不好。
注意:系統的SQL優化,只是避免最差的,選擇相對優的,未必能夠得到最好的優化結果。
11.用Case When替代UNION
兩個子查詢的表連線部分完全一樣
兩個子查詢除了取資料條件,其它都一樣。
Union all是多餘的,它需要重複掃描資料,進行重複的JOIN
可以用Case when替代union
12.用OR替代UNION
兩個子查詢的表連線部分完全一樣
兩個子查詢除了取資料條件,其它都一樣。
Union all是多餘的,它需要重複掃描資料,進行重複的JOIN
可以用OR替代union
此類的問題,在指令碼中經常見到。
13.Union和Union all
Union與Union all的作用是將多個SQL的結果進行合併。
Union將自動剔除集合操作中的重複記錄;需要耗更多資源。
Union all則保留重複記錄,一般建議使用Union all。
第一個SELECT語句,決定輸出的欄位名稱,標題,格式等
要求所有的SELECT語句:
1) 必須要有同樣多的表示式數目;
2) 相關表示式的域必須相容
14.先Group by再join
記錄數情況:t: 580萬,b: 9400萬, c:8, d:8
主要問題:假如連線順序為:( (b join c) join d) join t)
則是( (9400萬 join 8) join 8) join 580萬)
資料分佈時間長(IO多),連線次數多
解決方法:先執行(t join b),然後groupby,再join c,d
結果:
(1) VTDUR_MON join VTNEW_SUBS_THISYEAR
PI相同,merge join,只需10秒
(2)經過group by,b表只有332記錄
(3)b join c join d, 就是:
332 × 8 × 8
(4)最終結果:5記錄,共40秒
先彙總再連線,可以減少參與連線的資料集大小,減少比較次數,從而提高效率。
以下面SQL為例,假設歷史表( History )有1億條記錄
左邊的SQL,需要進行 1億 × 90次比較
右邊的SQL,則只需要 1億 × 1 次比較
15.SQL書寫不當可能會引起笛卡兒積
以下面兩個SQL為例,它們將進行笛卡兒積操作。
例子1:
Select
employee.emp_no
, employee.emp_name
From employee A
表Employee與表A進行笛卡兒積
例子2:
SELECT A.EMP_Name, B.Dept_Name
FROM employee A, Department B
Where a.dept_no = b.dept_no;
表A與表B進行笛卡兒積
表A與表B進行Inner Join
16.修改表定義
常見的表定義修改操作:
增加欄位
修改欄位長度
建議的操作流程
Rename table db.tablex as db.tabley;
通過Show table語句獲得原表db.tablex的定義
定義新表: db.tablex
Insert into db.tablex(。。。)
select 。。。 From db.tabley;
Drop table db.tabley;
Teradata提供ALTER TABLE語句,可進行修改表定義
但,不建議採用ALTER TABLE方式。
17.插入/更新/刪除記錄時,儘量不要Abort
當目標表有資料時,插入和更新操作,以及部分刪除,都產生TJ
如果此時abort該操作,系統將會回滾
對於大表進行Update/DELETE操作,將耗費相當多的資源與相當長的時間。
Update/Delete操作,需要事務日誌TJ(Transient Journal)
以防意外中斷導致資料受到破壞
在Update/Delete操作中途被Cancel,系統則需回滾,這將耗更多的資源與時間!
第三部分:Teradata工具實用小技巧
1.SQL變數
SELECT DATABASE; 顯示當前資料庫
PVIEW
SELECT USER; 顯示當前Session登陸的使用者名稱
lusc
SELECT DATE, CURRENT_DATE ; 顯示當前日期
20070806 , 20070806
定義格式: SELECT CAST(DATE AS DATE FORMAT 'YYYYMMDD')
Select TIME, CURRENT_TIMESTAMP(0);顯示當前時間
18:46:35, 2007-08-06 18:46:34+00:00
轉換: SELECT CAST(CURRENT_TIMESTAMP(0) AS CHAR(19));
2007-08-06 18:47:59
2.日期(DATE)的操作
取當前天:
select cast( current_date as DATE FORMAT 'YYYYMMDD')
取當前天的前一天,後一天
select cast( current_date -1 as DATE FORMAT 'YYYYMMDD')
select cast( current_date + 1 as DATE FORMAT 'YYYYMMDD')
取前(後)一個月的同一天
Select add_months(current_date , -1)
Select add_months(current_date , 1)
若current_date為20070331,結果是什麼?
取當前天所在月的第一天
select substr(cast(current_date as date format 'YYYYMMDD'),1,6) || '01';
取當前天所在月的最後一天
select cast( substr(cast( add_months(current_date,1) as date format 'YYYYMMDD'),1,6) || '01‘ as date format 'YYYYMMDD') -1
日期相減
SELECT ( DATE '2007-03-01' - DATE '2004-01-01') day(4);
SELECT (DATE'2007-03-01'- DATE'2004-01-01') month(4) ;
3.日曆表:Sys_calendar.Calendar
用於進行復雜的日期計算
判斷日期是否合法,例如20070229
SELECT * FROM Sys_calendar.Calendar
WHERE calendar_date = cast('2007-02-29' as date format ‘yyyy-mm-dd’);
返回空值,則說明該日期是非法的。
判斷某日歸屬當月(當年)的第幾周,當年的第幾季度等
Select week_of_month, Week_of_year, quarter_of_year
From Sys_calendar.Calendar
WHERE calendar_date = cast('2006-10-15' as date format 'yyyy-mm-dd');
取當前月的天數
Select max(day_of_month)
From Sys_calendar.Calendar
WHERE cast( cast(calendar_date as date format 'yyyymmdd') as char(8)) like '200708%‘
或 where month_of_calendar in (
select month_of_calendar
From Sys_calendar.Calendar
where calendar_date = cast('2007-08-01' as date format 'yyyy-mm-dd')
)
第四部分:JOIN的實現機制
1.LEFT Outer Join 舉例
SELECT E.Last_name
,E.Department_Number
,D.Department_Name
FROM Employee E LEFT OUTER JOIN
Department D
ON E.Department_Number = D.Department_Number
Last_Name Department_Number Department_Name
Crane 402 software support
James 111 ?
Runyon 501 marketing and sales
Stein 301 research and develop
Green ? ?
Trainer 100 executive
Kanieski 301 research and develop
內連線相比,這個查詢的結果集會增加下面的一些記錄:
部門號為空的員工。
部門號不在部門程式碼表裡面的員工。
2.Join之前的重分佈
Join 的列都是兩個表的PI 不需要資料重分佈.
SELECT . . .
FROM Table1 T1
INNER JOIN Table2 T2
ON T1.A = T2.A;
Join 的列都是在一個表上是PI,另外一個表上不是PI 是PI的表不需要重分佈.
SELECT . . .
FROM Table1 T1
INNER JOIN Table2
ON T1.A = T2.A;
3.複製小表到Spool空間
4.關聯策略 Merge Join
適用情況:
兩個表的資料量都比較大時
例如 100萬 × 30萬
用來Join的記錄必須位於相同的AMP上
Merge Join 僅僅讀取每個表一次.
對於等值條件的Join,優化器經常會選用Merge Join.
通常情況下比product join的效率更高.
Merge join 處理流程:
找到一個小表.
如果需要:
將一個或者兩個表要用到的資料都放在Spool空間裡.
基於Join列的hash值將記錄重分佈到相應的AMP.
根據Join列的hash順序對spool裡面的記錄進行排序.
對於Join列的Hash值相同的記錄進行比較.
與Product Join相比,比較次數大大降低.
5.關聯策略 Product Join
適用情況:
大表非PI欄位對小表
例如 30萬 × 50
不對記錄做排序
如果記憶體裡面放不下的時候需要多次讀取某張表.
Table1 的每條記錄要與 Table2 的每條記錄進行比對.
滿足條件的記錄會被放到 spool空間中.
之所以會被稱作Product Join 是因為:
總共的比較次數 = Table 1 的記錄條數 * Table 2的記錄條數
當記憶體裡面不能存放某一個表的所有資料的時候,這種比較會變得非常的消耗資源,因為總是需要內外存的交換。
如果沒有where條件,Product Join通常會產生無意義的結果.
Product Join 處理步驟:
找到小表並在Spool空間中複製到所有AMP上.
在每個AMP上,Spool空間裡的小表的每一行和大表在該AMP上的每一行做Join
6.關聯策略 Hash Join
適用情況:
大表非PI欄位對中等小的表
例如 700萬 × 1萬
優化器技術有效的將小表放在Cache記憶體中,並且與未排序的大表進行關聯.
Row Hash Join的處理流程:
找到小表.
重分佈小表或者複製小表到各個AMP的記憶體中.
將小表在Cache記憶體中按照join欄位的 row hash順序排序.
將記錄放在記憶體中.
用大表的join欄位的row hash在記憶體中進行折半查詢.
這種join將減少大表的排序、重分佈或者拷貝.
EXPLAIN 將會看見類似於“Single Partition Hash Join”的術語.
7.多表連線
多表連線可以分解為兩兩連線.
對下面的SQL,查詢引擎可以選擇較優的執行計劃:例如,Plan1或者Plan2。
SELECT …. FROM Table_A, Table_B, Table_C, Table_D WHERE . . . ;
對下面的SQL,查詢引擎只能選擇Plan2,否則結果有可能不對。
SELECT ….
FROM Table_A left join Table_B on A.c1 = B.c2
INNER JOIN Table_C ON B.c2 = c.c3
LEFT JOIN Table_D ON D.C4 = A.C1
WHERE . . . ;
第五部分:JOIN的優化
1.改變查詢計劃的手段
修改PI
收集統計資訊
關聯欄位上的統計資訊
Partition上的統計資訊
Where條件上的統計資訊
Group by 欄位上的統計資訊
檢視某個表的統計資訊情況:help stat DBName.TableName
檢視詳盡的統計情況:select * from pview.vw_statistic_info
通過Explain檢視,尚需統計哪些資訊?
diagnostic helpstats on for session;
2.JOIN問題的經驗分析
執行速度慢的SQL,絕大多數都是JOIN
例外1:INSERT操作慢,可能是因為目標表為set型別,或者PI不對
例外2:資料讀取慢,可能用like操作,或者資料本身就很大
JOIN的問題,主要在於:
資料分佈方式不對:把大表進行duplicate,或者redistribute
大表Redistribute有可能導致資料分佈不均衡
JOIN演算法不對:
例如,大表join小表,用merge join導致大表需要重新hash與sort
例如,大表join大表不用merge join
JOIN問題的解決辦法:
對參與join的欄位進行統計資訊
必要的時候,固化臨時表,並統計資訊
一般情況下,不需要調整SQL的業務邏輯