最具影响力的数字化技术在线社区

168主编 发表于 2017-3-24 11:48:27

基于MPP架构的TERADATA技术预览

/***************************************/
目录:
第一部分:Teradata架构
第二部分:常见问题,及解决方法
第三部分:Teradata工具实用小技巧
第四部分:JOIN的实现机制
第五部分:JOIN的优化
/***************************************/
第一部分:Teradata架构
1.相关概念
    SMP (Symmetrical Multi-Processing)对称多处理
    MPP (Massively Parallel Processing)大规模并行处理系统
    PE
    MPL
    AMP
    VDISK
    PI
    UPI
    NUPI
    PPI
http://blog.itpub.net/attachment/201502/1/30088512_1422795528u9au.png
2.Teradata 体系架构
http://blog.itpub.net/attachment/201502/1/30088512_1422795639Y4P7.png
    (1)数据存取架构图-数据存储
      步骤:                                    
      Parsing Engine分发需要写入的记录.               
      Message Passing Layer确定应管理记录的AMP               
      AMP将记录写入磁盘一个AMP管理一个逻辑存储单元            
      virtual disk (它对应多个物理的存储单元)
       http://blog.itpub.net/attachment/201502/1/30088512_14227957018jy1.png
    (2)Teradata数据存取架构图-数据读取
      步骤:                           
      Parsing Engine将数据读取请求发送到处理单元   
      Message Passing Layer确定要读取的记录属于哪个AMP管理
      AMP(s)定位要读取的记录的存储位置并读取.
      Message Passing Layer将结果记录反馈到PE               
      PE将结果记录反馈到请求端.
      http://blog.itpub.net/attachment/201502/1/30088512_1422795742IlCL.png
    (3)均匀的数据分布
      Notes:                                             
      每个表中的记录都会比较均匀地分布到各个AMP中.
      每个AMP中的都会存储系统中几乎所有表的数据.
      http://blog.itpub.net/attachment/201502/1/30088512_1422795883GVkM.png
    (4)完全线性扩展性
   http://blog.itpub.net/attachment/201502/1/30088512_1422796687Eb57.png
    (5)Primary Index 主索引
      利用PI访问数据的特点:
      总是使用一个AMP
      高效率的记录访问方式
      http://blog.itpub.net/attachment/201502/1/30088512_1422796758B1gK.png
    (6)Primary Index 主索引数据访问
      UPI 访问一个AMP,读取一条记录
      http://blog.itpub.net/attachment/201502/1/30088512_1422797032nOK7.png
      NUPI 访问一个AMP,读取多条记录
      http://blog.itpub.net/attachment/201502/1/30088512_1422797083YPjk.png
   (7)数据分布 1(UPI)
      http://blog.itpub.net/attachment/201502/1/30088512_1422797128yrlV.png
       数据分布 2(NUPI)
       http://blog.itpub.net/attachment/201502/1/30088512_142279716060J9.png
   (8)PI的选取
      重复值越少越好
      个数越少越好
      越经常使用越好
      少更新
      建表时要指定
      (9)PPI 例子
      http://blog.itpub.net/attachment/201502/1/30088512_1422797202qZg9.png


第二部分:常见问题,及解决方法
    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’);               
      返回空值,则说明该日期是非法的。                                                      
      判断某日归属当月(当年)的第几周,当年的第几季度等                                       
      Selectweek_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_dateas 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 Table1T1   
      INNER JOIN Table2T2
      ON T1.A = T2.A;
      http://blog.itpub.net/attachment/201502/1/30088512_1422797374pJDZ.png
      Join 的列都是在一个表上是PI,另外一个表上不是PI 是PI的表不需要重分布.
      SELECT . . .   
      FROM Table1T1
      INNER JOIN Table2
      ON T1.A = T2.A;
      http://blog.itpub.net/attachment/201502/1/30088512_1422797427scqh.png
    3.复制小表到Spool空间
    http://blog.itpub.net/attachment/201502/1/30088512_1422797464LsXn.png
    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_DWHERE . . . ;   
      对下面的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 . . . ;
   http://blog.itpub.net/attachment/201502/1/30088512_1422797545xgF4.png
第五部分: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的业务逻辑

来源: http://blog.itpub.net/30088512/viewspace-1423022/

页: [1]
查看完整版本: 基于MPP架构的TERADATA技术预览