1. 程式人生 > >基於MPP架構的TERADATA技術預覽

基於MPP架構的TERADATA技術預覽

/***************************************/
目錄:
第一部分: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的業務邏輯