暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

TD基础语法

万物可述 2021-06-29
3148


这是万物可述的第33篇原创文章



Teradata数据库介绍

什么是Teradata?

Teradada是用于世界上最大的商用数据库的关系数据库管理系统。

目前的技术允许数据库有数百Terabyte 字节的容量,这就使Teradata成为一个大型数据仓库应用的正确选择。而Teradata数据库系统也可以只有10G字节那么小。

由于并行性能和可扩展能力,Teradata可以使一个系统通过线性扩展从一个单一的节点开始扩展为多个节点的系统。


Teradata的特色:

  • 关系数据库

  • 海量处理能力

  • 数亿行的数据

  • Teradata字节的数据

  • 高性能的并行处理

  • 多客户端的单一数据库服务器

  • 网络和主机连接

  • 工业标准访问语言(SQL)

  • 通过模块化扩展的易管理性

  • 不同级别硬件和软件的容错能力

  • 数据完整性和可靠性


规划存储模型:

Teradata数据库支持行列混合存储。行、列存储模型各有优劣,建议根据实际情况选择。

行存储是指将表按行存储到硬盘分区上,列存储是指将表按列存储到硬盘分区上。默认情况下,创建的表为行存储。


行、列存储优缺点:

存储模型

优点

缺点

行存

数据被保存在一起。INSERT/

UPDATE容易。

选择(Selection)时即使只涉及某几列,

所有数据也都会被读取。

列存

1) 查询时只有涉及到的列会被读取。

2) 投影(Projection)很高效。

3) 任何列都能作为索引。

1) 选择完成时,被选择的列要重新组装。

2) INSERT/UPDATE比较麻烦。


一般情况下,如果表的字段比较多(大宽表),查询中涉及到的列不多的情况下,适合列存储。

如果表的字段个数比较少,查询大部分字段,那么选择行存储比较好。

存储类型

适用场景

行存

1) 点查询(返回记录少,基于索引的简单查询)。

2) 增、删、改操作较多的场景。

列存

1) 统计分析类查询 (关联、分组操作较多的场景)。

2) 即席查询(查询条件不确定,行存表扫描难以使用索引)。


行存表

默认创建表的类型。数据按行进行存储,即一行数据是连续存储。适用于对数据需要经常更新的场景。

    CREATE TABLE customer_t1
    (
    state_ID CHAR(2),
    state_NAME VARCHAR2(40),
    area_ID NUMBER
    );

    --删除表

    DROP TABLE customer_t1;


    列存表

    数据按列进行存储,即一列所有数据是连续存储的。单列查询IO小,比行存表占用更少的存储空间。适合数据批量插入、更新较少和以查询为主统计分析类的场景。列存表不适合点查询。

      CREATE TABLE customer_t2
      (
      state_ID CHAR(2),
      state_NAME VARCHAR2(40),
      area_ID NUMBER
      )
      WITH (ORIENTATION = COLUMN);

      --删除表

      DROP TABLE customer_t2;


      Teradata语法

      数据类型

      类型

      名字

      字节长度

      说明

      数值型

      DATE

      4

      YYMMDD,特殊的INTEGER类型

      DECIMAL(n,m)

      1,2,4,8

      n: 1~18, m: 0~n,可缩写成DEC。

      如256.78可表示为DEC(5,2)

      NUMERIC(n,m)

      1,2,4,8

      同上

      BYTEINT

      1

      128~+127

      SMALLINT

      2

      32768~+32767

      INTEGER

      4

      可缩写成INT


      REAL

      8

      FLOAT

      8

      同上

      DOUBLE PRECISION

      8

      同上

      字符型

      CHAR(n)

      n

      n: 1~64000,也可写成CHARACTER

      VARCHAR(n)

      n+2

      n: 1~64000,变长,最前面两字节表示字符串

      长度。也可写成CHAR VARYING(n)

      LONG VARCHAR

      32002

      相当于VARCHAR(64000)

      二进制

      BYTE(n)

      n

      n: 1~64000,无符号二进制整数

      VARBYTE(n)

      n+2

      n: 1~64000,变长,最前面两字节表示长度

      其它

      GRAPHIC(n)

      n

      n: 1~32000,这三种数据类型可支持双字节日

      本字符和汉字

      VARGRAPHIC

      n+2

      n: 1~32000,变长,最前面两字节表示长度

      LONG VARGRAPHIC


      相当于VARGRAPHIC(32000)



      • 算术运算符

      Teradata提供以下ANSI标准规定的算术运算符:

      * 乘

      / 除

      + 加

      - 减

      + 正号

      - 负号


      除此以外,Teradata还扩展了下面两个算术运算符:

      ** (求幂)

      MOD(取模)


      **表示方法:**,

      例:

      4**3 = 4 * 4 * 4 = 64


      MOD是取模运算符,表示除运算的余数。

      例:

      60 MOD 7 = 4

      即:60除以7等于8,余数是4。


      Teradata 算术函数

      在ANSI标准中没有算术函数,Teradata作了扩充,它支持的算术函数如表所示。

      函数

      意义

      ABS (arg)

      求绝对值

      EXP (arg)

      增加幂

      LOG (arg)

      10的对数

      LN (arg)

      自然对数

      SQRT (arg)

      平方根

      注:arg代表任意常数或变量。

      例:

      SQRT(16) = 4


      创建表

      CREATE TABLE语句创建新表,定义新表的列、索引和其他属性。新表创建后,表结构定义存放在Teradata的数据字典中。CREATE TABLE语句的语法如下:

      CREATETABLE;


      其中:

      Create Table Options

      表选项

      定义表的物理属性

      Fallback

      Journaling

      Freespace

      Datablocksize

      Column Definitions字段定义

      定义表的各个字段

      Table-level Constraints

      表级约束

      定义约束

      Primary key

      Unique

      CHECK条件

      Foreign key

      Index Definitions索引定义

      定义表索引


      创建表的可选项

      Teradata DDL允许在创建表时指定表的物理属性,包括:

       1)是否允许重复记录

      ❍ SET 不允许记录重复

      CREATE SET TABLE table1 ...


      ❍ MULTISET 允许记录重复

      CREATE MULTISET TABLE table1 ...


       2)数据保护

      数据保护要结合FALLBACK和JOURNAL (流水或日志)。

      FALLBACK是Teradata的一种数据保护机制,数据表的每一条记录都同时存放两份,而且位于不同的AMP所控制的存储单元中;当数据发生问题或者AMP失败时,可以利用存放在其他AMP上的数据保证对数据表的访问。

      - FALLBACK 使用FALLBACK保护机制

      - NO FALLBACK 不使用FALLBACK保护机制


      日志有BEFORE和AFTER两种,分别保存了一条记录变化前后的状态。当系统出错时,可以利用日志进行恢复。


      存储空间选项

      DATABLOCKSIZE用来指定数据块大小,最小的数据块为6144字节,最大的数据块是32256字节。

      FREESPACE用来定义在每个磁盘柱面上保留的空间(0-75%)。

      例:

        CREATE MULTISET TABLE table_1
        , FALLBACK, NO JOURNAL
        , FREESPACE = 10 PERCENT
        , DATABLOCKSIZE = 16384 BYTES
        (field1 INTEGER);


        Teradata新增命令

        在Teradata中,主要增加了以下命令:

        命令

        功能

        HELP

        帮助用户了解数据库中各种对象的结构

        SHOW

        帮助用户了解某种对象的定义,即返回其DDL语句

        EXPLAIN

        返回一个SQL语句经优化处理后的执行步骤,注意并未真正执行

        FALLBACK

        对数据加以保护的一种方式,是冗余的备份

        RENAME

        对表重命名

        NULLIFZERO

        对数据作累计处理时,忽略零值

        ZEROIFNULL

        对数据作累计处理时,将空值作零处理

        WITH...BY

        对详细数据记录作分类统计(Sub-Total)时有用

        MODIFY USER

        /DATABASE

        对用户/数据库对象作动态修改而无需数据库重组


        HELP命令

        HELP命令可以用来显示数据库中各个目标的相关信息、当前对话连接的特性,并能提供SQL语法的联机帮助。


        数据库中的对象包括表、视图、宏、触发器和存储过程,HELP命令可以提供有关数据库和用户以及这些对象的信息。


        HELP命令

        参数

        HELP DATABASE

        databasename;

        HELP USER

        username;

        HELP TABLE

        tablename ;

        HELP VIEW

        viewname;

        HELP MACRO

        macroname;

        HELP COLUMN

        table or viewname.*;

        HELP COLUMN

        table or viewname.colname . . ., colname;

        HELP INDEX

        tablename;

        HELP STATISTICS

        tablename;

        HELP CONSTRAINT

        table or viewname.constraintname;

        HELP JOIN INDEX

        join_indexname;

        HELP TRIGGER

        triggername;

        HELP PROCEDURE

        procedurename;

        HELP PROCEDURE

        procedurename ATTRIBUTES;


        例:

        HELP DATABASE/USER 的使用


        HELP DATABASE可以显示一个指定数据库所包含的所有对象,如表、视图、宏等。如要显示数据库customer_service中的对象,可以使用下面的命令:

        HELP DATABASE customer_service;


        系统返回信息如下:

        Table/View/Macro name

        Kind

        Comment


        contact

        T

        ?

        customer

        T

        ?

        department

        T

        ?

        employee

        T

        ?

        employee_phone

        T

        ?

        job

        T

        ?

        location

        T

        ?

        location_employee

        T

        ?


        这里返回了三列信息。第一列是表、视图或宏的名字,第二列则是类型,T表示表(Table),V表示视图(View),M则表示宏(Macro)。第三列表示注释,?表示没有注释。


        同理,如果要显示某个用户中所包含对象的信息,则可以使用HELP USER命令。如下面的命令将显示DBC用户下所包含的所有对象:

        HELP USER DBC;


        SHOW命令

        查看数据库对象是用什么样的DDL命令创建。


        针对数据库对象的HELP命令:

        SHOW命令

        参数

        SHOW TABLE

        Tablename ;

        SHOW VIEW

        Viewname;

        SHOW MACRO

        Macroname;

        SHOW INDEX

        Tablename;

        SHOW JOIN INDEX

        join_indexname;

        SHOW TRIGGER

        Triggername;

        SHOW PROCEDURE

        Procedurename;


        BTEQ还有一个SHOW命令,SHOW CONTROL,这是一个附加的SQL SHOW命令。它能够格式化显示当前BTEQ会话的信息。


        SHOW TABLE/VIEW/MACRO 的使用

        如果要显示EMPLOYEE表的结构,可使用下面的命令:

        SHOW TABLE customer_service.employee;

        系统返回信息如下:

          CREATE SET TABLE customer_service.employee ,FALLBACK ,
          NO BEFORE JOURNAL,
          NO AFTER JOURNAL
          (
          employee_number INTEGER,
          manager_employee_number INTEGER,
          department_number INTEGER,
          job_code INTEGER,
          last_name CHAR(20) NOT CASESPECIFIC NOT NULL,
          first_name VARCHAR(30) NOT CASESPECIFIC NOT NULL,
          hire_date DATE NOT NULL,
          birthdate DATE NOT NULL,
          salary_amount DECIMAL(10,2) NOT NULL)
          UNIQUE PRIMARY INDEX ( employee_number );


          由此可知,SHOW TABLE的命令返回了指定表的DDL语句。


          EXPLAIN 命令

          利用EXPLAIN命令,可以了解Teradata执行一个SQL交易请求的详细过程和计划,这对于更进一步地理解Teradata的查询处理机制有很大的帮助。另一方面,对于复杂SQL交易的调试来说,这也是不可缺少的一个工具。


          利用EXPLAIN解释一个SQL交易的方法很简单,就是在原来SQL语句的前面加上EXPLAIN即可,其它完全不变。系统返回的信息包括:

          1) 提供完整的由分解器对 SQL语句进行分解和优化后的 AMP执行步。

          2) 这种执行计划是基于当前的数据分布情况而作出的,因此当数据分布发生变化时,同样 SQL语句产生的执行步可能不相同。

          3) EXPLAIN 还会产生执行每个 SQL步骤大致所需要的时间,但需要注意的是,这个时间由于是根据早期版本的 CPU 处理时间来计算,因此往往和实际情况相差很多,仅能作参考而已。

          下面让我们来举个例子进行说明。


          假设一个如下的SQL语句:

          SELECT * FROM department;

          该语句非常简单,从DEPARTMENT表中将所有的记录选择并显示出来。如果要看一下它的执行过程,而不需要实际的结果,可以在前面加上EXPLAIN,如下:

          EXPLAIN SELECT * FROM department;

          系统返回信息如下:

            Explanation
            1) First, we lock CUSTOMER_SERVICE.department for read.
            2) Next, we do an all-AMPs RETRIEVE step from CUSTOMER
            _SERVICE.department by way of an all-rows scan with no residual conditions into Spool
            1, which is built locally on the AMPs. The size of Spool 1 is estimated to be 4 rows. The
            estimated time for this step is 0.08 seconds.
            3) Finally, we send out an END TRANSACTION step to all AMPs involved in
            processing the request.
            -> The contents of Spool 1 are sent back to the user as the result of statement 1.
            The total estimated time 0.08 seconds.

            从系统返回的信息可以看到,该SQL请求是一个牵涉到所有AMP的操作(All-AMP Operation)。对于一个复杂的SQL交易请求,如果执行出错(如空间溢出等)或返回结果与所预料的相差很远,则有可能是SQL语句本身存在问题。这时可以利用EXPLAIN机制来了解一下Teradata的处理过程,从而发现和解决问题。

            宏(Macro)是Teradata扩展的性能,ANSI标准不支持宏。


            宏(Macro)的基本特征是:

            1) 可以包含一条或多条 SQL语句

            2) 可以包含多个 BTEQ语句

            3) 可以包含注解

            4) 存储在数据字典中


            Teradata中用于宏的命令:

            CREATE MACRO macroname AS ( . . . );

            定义宏

            EXECUTE macroname;

            执行宏语句

            SHOW MACRO macroname;

            显示宏定义

            REPLACE MACRO macroname AS (. . . );

            改变宏定义

            DROP MACRO macroname;

            从字典中删除宏定义

            EXPLAIN EXEC macroname;

            显示宏执行的解释


            宏的定义

            宏是用CREATE MACRO命令来定义的,如下例所示:

            CREATE MACRO birthday_list AS

            (SELECT last_name

            ,first_name

            ,birthdate

            FROM employee

            WHERE department_number = 201

            ORDER BY birthdate; );


            宏的执行

            宏的执行很简单,使用EXEC命令就可以。例如,为了执行上面定义的宏,可以使用下面的语句:

            EXEC birthday_list;


            宏的删除

            使用DROP命令可以删除宏,如下所示:

            DROP MACRO birthday_list;


            宏的显示和改变

            使用SHOW命令可以显示一个宏的定义,如下所示:

            SHOW MACRO birthday_list;


            使用REPLACE MACRO命令可以改变宏的定义,如:

            REPLACE MACRO birthday_list AS

            (SELECT last_name

            ,first_name

            ,birthdate

            FROM employee

            WHERE department_number = 201

            ORDER BY birthdate, last_name; ) ;


            参数宏

            所谓参数宏,是指在宏中包含可以替代值的变量。下面是一个简单的参数宏定义:

            CREATE MACRO dept_list(dept INTEGER)

            AS

            ( SELECT last_name

            FROM employee

            WHERE department_number = :detpt );

            该宏的功能是在雇员表中选取某个部门全部雇员的姓,宏dept_list定义了一个参数dept,类型是整数。作为部门代码参数。


            运行宏dept_list的语句为:

            EXEC dept_list(301);

            其结果是返回部门编号为301的所有雇员的姓。

            如同这个简单的例子,参数在宏中的引用是通过冒号(:) +参数名而实现的。


            FORMAT 短语

            FORMAT用于数据在输出时的格式化处理,但它并不影响数据的内部存储格式。它主要有如下面例子所示的两种表示方式。

            例:

            SELECT salary_amount (FORMAT ''$$$,$$9.99'');

            例:

            SELECT CAST (salary_amount AS FORMAT ''$$$,$$9.99'');

            注意,在第二个例子中CAST的使用方法是Teradata的扩展,因为这里CAST处理的是一个数据的属性,而在ANSI标准中,CAST只能用于处理一种数据类型。


            FORMAT短语中可以使用的格式化字符主要为:

            1) $ 美元标识符

            2) 9 数字位

            3) Z 将数字中的前缀零去除

            4) , 在指定位置插入逗号

            5) . 指定小数点位置

            6) - 在指定位置插入连字号

            7) 在指定位置插入斜线

            8) % 在指定位置插入百分号

            9) X 字符数据,每个 X代表一个字符

            10) G 图形数据.一个 G代表一个逻辑字符(双字节)

            11) B 在指定位置插入空格


            对日期的格式化处理

            在Teradata中,日期数据的缺省输出格式是:YY/MM/DD,这和ANSI标准是一样的。而ANSI标准建议的日期显示格式是:YYYY-MM-DD。


            其它一些常用的日期显示格式列举如下,其中的B表示空格。

            YYYY/MM/DD'

            YYYY-MM-DD'

            YYYY.DDD'

            DBMMMBYYYY'

            MMBDD,BYYYY'

            YYYYBMMMBDD'

            YY/MM/DD'

            D-MM-YY'

            YBDDD

            MM'

            注意:由于2000年问题,ANSI推荐使用日期格式为YYYY-MM-DD,或者其它采用四位年的格式。

            下面是一些对日期进行格式化的例子。

            句法 结果

              FORMAT 'YYYY/MM/DD' 1996/03/27
              FORMAT 'DDbMMMbYYYY' 27 Mar 1996
              FORMAT 'mmmBdd,Byyyy' Mar 27, 1996
              FORMAT 'DD.MM.YYYY' 27.03.1996
              FORMAT 'MM/DD/YY' 03/27/96
              FORMAT 'MMM.DD.YY' Mar.27.96
              FORMAT 'yy -- mm -- dd' 96 -- 03 -- 27
              FORMAT 'DDDYY' 08696


              下面再看一下在SELECT语句中对日期进行格式化的例子。

                SELECT last_name
                ,first_name
                ,hire_date (FORMAT 'mmmBdd,Byyyy')
                FROM employee
                ORDER BY last_name;
                last_name first_name hire_date
                Johnson Darlene Oct 15, 1976
                Kanieski Carol Feb 01, 1977
                Ryan Loretta Oct 15, 1976


                总计与小计

                利用WITH BY 进行数据小计

                WITH BY的主要特点包括:

                1) 它为明细数据表创建分类小计。

                2) 跟 GROUP BY不同的是,WITH BY没有剔除明细记录,而是在明细记录后面按照分类增加小计行。

                3) 可以允许多于一个字段进行小计,即小计当中可以嵌套小计。

                4) 输出结果将根据 BY 后面的所有字段自动进行排序。

                5) 它是 Teradata的一个扩展特性。


                请看下面的一些例子。为了说明方便,在下面的诸例子中均利用了雇员表。

                1.利用WITH BY产生基本报表。

                例如在Employee表中,欲显示所有雇员姓和工资并要求按部门进行小计。其语句如下:

                  SELECT last_name AS NAME
                  ,salary_amount AS SALARY
                  ,department_number AS DEPT
                  FROM employee
                  WITH SUM (salary) BY DEPT;

                  返回的报表如下所示:

                    NAME SALARY DEPT
                    Stein 29450.00 301
                    Kanieski 29250.00 301
                    --------------
                    Sum(SALARY)58700.00
                    Johnson 36300.00 401
                    Trader 37850.00 401
                    --------------
                    Sum(SALARY)74150.00
                    Villegas 49700.00 403
                    Ryan 31200.00 403
                    --------------
                    Sum(SALARY) 80900.00


                    利用WITH语句产生最后的总计

                    如果在WITH语句中不带BY则只产生总计。如下面的例子:

                    列出部门301所有的雇员编号和其工资数,并对该部门的工资作统计,语句如下:

                      SELECT employee_number
                      ,salary_amount
                      FROM employee
                      WHERE department_number = 301
                      WITH SUM(salary_amount) (TITLE 'GRAND TOTAL')
                      ORDER BY employee_number;


                      返回结果如下:

                        employee_number salary_amount
                        1006 29450.00
                        1008 29250.00
                        1019 57700.00
                        -------------
                        GRAND TOTAL 116400.00

                        SUBSTRING 函数

                        SUBSTRING函数用来从字符串中析取一个子字符串,其格式为:

                        SUBSTRING (<字符串表达式> FROM <开始位置> [ FOR <长度> ])

                        如:

                        SELECT SUBSTRING('catalog' FROM 5 FOR 3);

                        结果为log。


                        字符串合并

                        字符串合并的符号是"||",它把两个字符串串联成一个字符串。其基本格式为:

                        <字符串1> || <字符串2>

                        NULLIF 表达式

                        NULLIF实际上用来作为CASE语句在某种情况下的缩写,其格式为:

                        NULLIF (,)

                        规则是:

                            a. 如果表达式 1等于表达式 2,则返回 NULL

                            b. 如果表达式 1不等于表达式 2,则返回表达式 1的值

                        例:

                          SELECT  call_number
                          ,labor_hours (TITLE 'ACTUAL HOURS')
                          ,NULLIF (labor_hours, 0) (TITLE 'NULLIF ZERO HOURS')
                          FROM call_employee
                          ORDER BY labor_hours;


                          NULLIF等价于:

                          CASE 

                          WHEN=THEN NULL

                                         ELSE   

                          END


                          OLAP 函数

                          OLAP即联机分析处理(On-Line Analytical Process)。Teradata数据库本身提供了一些OLAP函数,包括:

                          RANK - 排队(Rankings)

                          QUANTILE - 分位数(Quantiles)

                          CSUM - 累计(Cumulation)

                          MAVG - 移动平均(Moving Averages)

                          MSUM - 移动合计(Moving Sums)

                          MDIFF - 移动差分(Moving Differences)

                          MLINREG - 移动线性回归(Moving Linear Regression)


                          OLAP函数与聚合函数有类似的地方:

                          1) 对数据进行分组操作 (类似于 GROUP BY 子句)

                          2) 能够使用 QUALIFY 子句过滤组 (类似于 HAVING 子句)


                          OLAP函数又与 聚合函数不同,因为:

                          1) 返回满足条件的每行的数据值,而不是组的值

                          2) 不能在子查询内使用


                          下面列举一些常用的OLAP函数。


                          累计函数

                          累计函数(CSUM) 计算一列的连续的累计的值。语法为:

                          CSUM(colname, sort list)


                          问题

                          创建item 10从1998年1月和2月的连续的日汇总报表。

                          解答

                          SELECT salesdate, sales, csum(sales, salesdate)

                          FROM daily_sales

                          WHERE salesdate BETWEEN 980101 AND 980301

                          AND itemid = 10;

                          结果

                            salesdate sales Csum
                            98/01/01 150.00 150.00
                            98/01/02 200.00 350.00
                            98/01/03 250.00 600.00
                            98/01/05 350.00 950.00
                            98/01/10 550.00 1500.00
                            98/01/21 150.00 1650.00
                            98/01/25 200.00 1850.00
                            98/01/31 100.00 1950.00
                            98/02/01 150.00 2100.00
                            98/02/03 250.00 2350.00
                            ......


                            如果想每月重新累计,该怎么办?

                            累计汇总可以使用GROUP BY子句在特殊的点复位,即重新开始累计。注意,OLAP函数和标准聚合函数(SUM, COUNT,AVG, MIN, MAX) 是不能在同一查询中兼容的。因此,对这类查询使用GROUP BY,将会起分隔的作用。


                            问题:

                            创建item 10从1998年1月和2月的连续的日汇总报表,并且每月重新开始累计。

                            解答:

                              SELECT salesdate, sales, csum(sales, salesdate)
                              FROM daily_sales ds, sys_calendar.calendar sc
                              WHERE ds.salesdate = sc.calendar_date
                              AND sc.year_of_calendar = 1998
                              AND sc.month_of_year in (1,2)
                              AND ds.itemid = 10
                              GROUP BY sc.month_of_year;

                              结果:

                                salesdate sales Csum
                                98/01/01 150.00 150.00
                                98/01/02 200.00 350.00
                                98/01/03 250.00 600.00
                                98/01/05 350.00 950.00
                                98/01/10 550.00 1500.00
                                98/01/21 150.00 1650.00
                                98/01/25 200.00 1850.00
                                98/01/31 100.00 1950.00
                                98/02/01 150.00 150.00 重新累计
                                98/02/03 250.00 400.00
                                98/02/06 350.00 750.00
                                98/02/17 550.00 1300.00
                                98/02/20 450.00 1750.00
                                98/02/27 350.00 2100.00

                                排队函数

                                排队函数对一列进行排队,可以按照升序或者降序排队。缺省,输出结果按照降序排队,对应的排队名次是升序。换句话说,如果一个销售代表在某季度的销售额最高,其排名为1,这是一个最小的值。

                                排队函数(RANK)的语法是:

                                RANK(colname)


                                显示商店1001的产品销售额排队。

                                解答:

                                  SELECT storeid, prodid, sales, RANK(sales)
                                  FROM salestbl
                                  WHERE storeid = 1001;

                                  结果:

                                    storeid prodid sales Rank
                                    1001 F 150000.00 1
                                    1001 A 100000.00 2
                                    1001 C 60000.00 3
                                    1001 D 35000.00 4


                                    使用排队函数的规则包括:

                                    1) WHERE 子句限定参与排队的记录。

                                    2) 应用排队函数时,缺省最大的数名次最低。

                                    3) 缺省顺序是按排队列的降序。


                                    带限定的排队

                                    QUALIFY子句限制排队输出的最终结果。QUALIFY子句与HAVING子句类似,使输出限制在一定范围内。


                                    问题

                                    按商店得到销售前3名的产品。

                                    解答

                                      SELECT storeid, prodid, sales, rank(sales)
                                      FROM salestbl
                                      GROUP BY storeid
                                      QUALIFY rank(sales) <= 3;

                                      结果

                                        storeid prodid sales Rank
                                        1001 A 100000.00 1
                                        1001 C 60000.00 2
                                        1001 D 35000.00 3
                                        1002 A 40000.00 1
                                        1002 C 35000.00 2
                                        1002 D 25000.00 3
                                        1003 B 65000.00 1
                                        1003 D 50000.00 2
                                        1003 A 30000.00 3

                                        上面的例子中,GROUP BY子句不是做聚合,它实际上是改变查询的范围,也引起排序。

                                        使用排队函数的规则包括:

                                        1) 对某列的每行都应用了排队

                                        2) GROUP BY 子句控制范围,如商店内的销售额排队(注意- 查询中并没有聚合)

                                        3) QUALIFY 子句限制显示,如仅显示销售额的前 3名

                                        4) 缺省的顺序是按照排队的列的降序

                                        5) 因为 GROUP BY 子句,排序将限制在组内,如商店内。


                                        临时表

                                        Teradata中有3类临时表:

                                        1)全局临时表(Global Temporay Table)

                                        2)可变临时表(Volatile Temporay Table)

                                        3)导出表(Derived Table)


                                        为什么使用临时表?

                                        临时表是一种辅助工具,能够提高SQL操作的性能。特别是针对下列情况的SQL操作:

                                        1)不能使用规范化的表;

                                        2)要求多条 SQL语句完成。


                                        临时表对于非规范化非常有用,如:

                                        1)汇总表

                                        2)重复分组


                                        临时表对于频繁产生的中间结果或作为后续工作基础的中间结果也非常有用。


                                        可变临时表(Volatile Temporary Tables)

                                        可变临时表在Teradata V2R3中实现,与导出表相比,它有许多优点。其特点包括:

                                        1)对会话(session)是本地的 - 存在于整个会话期间,而不是单个查询。

                                        2)使用 CREATE VOLATILE TABLE语法创建。

                                        3)会话(session)结束时,自动丢掉。

                                        4)不使用数据字典。


                                        全局临时表(Global Temporary Tables)

                                        全局临时表在Teradata V2R3中实现,与可变临时表的主要区别是,全局临时表在数据字典中有定义,可以被多个用户共享。每个用户会话能够物化自己本地的表的实例。其特点包括:

                                        1)对会话(session)是本地的,但是每个用户会话可以有自己的实例。

                                        2)使用 CREATE GLOBAL TEMPORARY TABLE 语法。

                                        3)会话(session)结束时,物化的表的实例被丢掉。

                                        4)在数据字典中创建并保持表的定义。


                                        全局临时表与可变临时表有不同的地方:

                                        1)基础定义是永久的,保存在数据字典中。

                                        2)要物化表,要有相应 SQL的权限。

                                        3)空间要占用用户的“临时空间(temporary space)”。

                                        4)每个会话最多可以物化 32个全局临时表。

                                        5)系统重启动后,还存在。


                                         全局临时表与可变临时表有相似的地方:

                                        1)对会话而言,每个实例是本地的。

                                        2)会话结束后,物化的表被自动删除。(但基础定义仍然存储在数据字典中)

                                        3)都有 LOG 和 ON COMMIT PRESERVE/DELETE 选项。

                                        4)物化表中内容与其他会话不共享。

                                        5)在会话开始时,表被清空。


                                        索引

                                        索引是物理模型中的一个概念,利用索引,可以直接存取表中的某一条记录而不需要搜索整个表。因此,索引提供了一条更快速访问数据记录的途径。


                                        当在数据库中针对某个表创建一个索引时,系统将根据此索引建立一个相应的子表。相对原来的表(主表)而言,子表要小得多。它将存储索引的值以及一个与此索引对应的数据记录在主表中的存储位置,这好比一个指向数据记录物理位置的指针。显然,建立索引需要占用额外的存储空间;另外,索引子表是由系统自动维护的,当主表的数据记录发生变化时,系统要自动更新索引子表的相应记录,从而占用系统资源。这就是使用索引的代价。


                                        索引则存在于物理模型中。Teradata中又把索引分为主索引和次索引,主索引不一定就对应主键。


                                        选择主索引的基本原则是:尽量选择那些访问频率高的属性作为主索引。


                                        主索引与主键的区别可以总结下表

                                        主键

                                        主索引

                                        逻辑模型中的一个概念

                                        物理模型中用于数据分配与存取的一种物

                                        理机制

                                        没有属性数目的限制

                                        最多由16个属性组成

                                        在逻辑模型中定义

                                        在创建表时定义

                                        取值必须唯一

                                        可以唯一也可以不唯一

                                        用来区分数据记录

                                        用来进行数据分配

                                        其值不发生改变

                                        其值可以发生变化

                                        不可以取空值

                                        可以取空值


                                        Teradata的每个表都必须有主索引。除主索引是必须的外,也可以建立次索引来提高表的存取性能和实现约束。相关的术语如下:

                                        PK

                                        Primary Key 主键

                                        PI

                                        Primary Index 主索引

                                        UPI

                                        Unique Primary Index唯一性主索引

                                        NUPI

                                        Non Unique Primary Index 非唯一性主索引

                                        USI

                                        Unique Secondary Index 唯一性次索引


                                        索引可以在CREATE TABLE时就加以定义,同时还可以定义主键。如果创建表时不定义主索引,Teradata就按照下面的规则缺省来建立主索引,因为没有主索

                                        引的话,Teradata就无法进行数据的分配。

                                        1.没有在 CREATE TABLE时指定 PI

                                        IF 定义了PK,THEN PK = UPI

                                        ELSE IF 存在定义为UNIQUE的字段,

                                        THEN 第一个NIQUE的字段为UPI

                                        ELSE 表中定义的第一个字段作为NUPI


                                        2. CREATE TABLE 时指定了 PI

                                        IF 定义了PK,THEN PK作为USI

                                        AND为每一个定义为UNIQUE的字段建立一个USI


                                        创建表时就应定义主索引,同时也可以定义次索引。事实上,次索引也可以使用单独的CREATE INDEX语句来定义。换言之,主索引只能在CREATE TABLE时定义,而次索引既可以在创建表时定义,也可以使用CREATE INDEX来定义。


                                        例:为雇员表创建下面两个次索引。

                                        为雇员名字建立命名的唯一次索引USI

                                        CREATE UNIQUE INDEX fullname (last_name, first_name)

                                        ON emp_data;


                                        为工作代码建立非唯一性次索引NUSI,不命名NUSI

                                        CREATE INDEX (job_code) ON emp_data;


                                        从这个例子可以看到,次索引可以命名,如第一个USI的名字为

                                        FULLNAME;也可以不命名,如第二个NUSI就没有取名。

                                        定义好索引或次索引后,可以利用HELP INDEX <表名>来显示指定表的所有

                                        索引定义,如果索引是未命名的,索引名称显示为NULL。


                                        优化思路及方法

                                        □ 选择目标

                                           √  执行时间长的ETL作业

                                           √  执行时间长的SQL操作

                                           √  I/O倾斜率高的SQL

                                           √  Spool使用多的SQL


                                        □ 收集信息

                                           √  目标SQL

                                           √  相关表的定义(特别是PI,PPI)

                                           √  相关表的大小


                                        □ Explain分析-1 EXPLAIN常用名称

                                        数据扫描:

                                          √  All-AMPs retrieve step         --全表扫描

                                          √  by way of all-row scan         --全表扫描

                                          √  by way of the primary index    --单PI查询

                                          √  Single-AMP retrieve step       --单个AMP检索

                                          √  all-Partions retrieve          --全分区检索


                                        数据JOIN前数据处理策略

                                           √  redistribution                --重分布

                                           √  duplicated on all AMPs        --全表复制


                                        数据关联方式   

                                           √  using a product join               

                                           √  using a single partion hash join   

                                           √  using a merge join  


                                        □ Explain分析-2 执行计划判断依据

                                          √  大表不应该发生all-AMPs Duplicated  --全表复制

                                          √  大表应尽量避免all-AMPs Redistributed  ----全表重分布

                                          √  小表应尽量all-AMPs Duplicated或all-AMPs Redistributed

                                          √  在多表进行关联的时候,应避免大表与大表先发生关联。

                                          √  分区表首先进行分区筛选,尽可能避免all-Partitions retrieve(全分区索引)


                                        □ 过程优化

                                          √  PDM模型

                                              ●调整PI

                                              ●使用PPI

                                              ●其他设计(multiset)


                                          √  SQL技术调整

                                              ●增加统计信息,改善执行计划

                                              ●减少不必要的数据排重

                                              ●复用和减少临时表

                                              ●大表预处理,减少结果集

                                              ●代码共用


                                          √  SQL逻辑调整

                                              ●减少大表的访问,直接引用其他结果

                                              ●简化业务规则,避免和大表关联


                                        优化总结:

                                        √ 保持良好的SQL书写习惯,格式对齐,关键字突出

                                        √ 越简单越美丽,不要追求高大上的复杂SQL

                                        √ 尽可能减少I/O和SPOOL

                                           ●数据的全表扫描使用PI或PPI

                                           ●大表的数据分布(使用PI)

                                           ●大表的数据复制(两张表数据量级相差较大时,小表进行数据复制)     

                                           ●不必要的比较和不必要的中间结果(先筛选数据后进行比较) 

                                         √  减少导出目标列的数量(按需选择)

                                         √  优化不能更改业务逻辑 

                                               

                                               

                                        作者:谢光琨

                                        编辑:徐菲





                                        据说中国有句古语叫「金无足赤,人无完人」,但是,如果谁真的想打起灯笼来到市面上寻找完人,最终令他感到的可能不是一种失望,而是一种意外:完人可能就是那些终日为「善」而奔走,而又在不知不觉中实现了「美」的「真」实不虚的普通人。

                                        追求完美是正常而有缺憾的人性。

                                        --尼采

                                        文章转载自万物可述,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                        评论