Teradata 简明教程
Teradata - Introduction
What is Teradata?
Teradata 是流行的关系数据库管理系统之一。它主要适用于构建大型数据仓库应用程序。Teradata 通过并行性的概念实现了这一点。它是由 Teradata 公司开发的。
History of Teradata
以下是 Teradata 历史的快速摘要,列出了主要里程碑。
-
1979 - Teradata 成立。
-
1984 - 发布第一台数据库计算机 DBC/1012。
-
1986 - 《财富》杂志将 Teradata 评为“年度产品”。
-
1999 - 使用 Teradata 的世界上最大的数据库,容量为 130 TB。
-
2002 - 发布带有分区主索引和压缩功能的 Teradata V2R5。
-
2006 - 推出 Teradata 主数据管理解决方案。
-
2008 - 发布了带有主动数据仓库的 Teradata 13.0。
-
2011 - 收购 Teradata Aster,并进入高级分析领域。
-
2012 - 引入了 Teradata 14.0。
-
2014 - 引入了 Teradata 15.0。
Features of Teradata
以下是 Teradata 的一些功能 -
-
Unlimited Parallelism - Teradata 数据库系统基于大规模并行处理 (MPP) 架构。MPP 架构均匀地将工作负载划分为整个系统。Teradata 系统在其流程之间拆分任务,并并行运行这些流程以确保快速完成任务。
-
Shared Nothing Architecture - Teradata 架构称为无共享架构。Teradata 节点、其访问模块处理器 (AMP) 和与 AMP 关联的磁盘独立运行。它们与他人不共享。
-
Linear Scalability - Teradata 系统具有很高的可扩展性。它们可以扩展到 2048 个节点。例如,可以通过将 AMP 的数量加倍来将系统容量加倍。
-
Connectivity - Teradata 可以连接到信道连接系统,例如大型机或网络连接系统。
-
Mature Optimizer - Teradata 优化器是市场上成熟的优化器之一。它从一开始就被设计为并行的。它针对每个版本进行了优化。
-
SQL - Teradata 支持工业标准 SQL 来与存储在表中的数据进行交互。除此之外,它还提供了自己的扩展。
-
Robust Utilities - Teradata 提供了强大的实用工具来从 Teradata 系统导入/导出数据,例如 FastLoad、MultiLoad、FastExport 和 TPT。
-
Automatic Distribution - Teradata 会自动将数据均匀分布到各个磁盘,而无需任何人工干预。
Teradata - Installation
Teradata 提供了适用于 VMWARE 的 Teradata Express,这是一个全面运行的 Teradata 虚拟机。它提供了高达 1 TB 的存储空间。Teradata 同时提供了 40 GB 和 1 TB 版本的 VMware。
Installation Steps for Windows
Step 1 − 从以下链接下载所需 VM 版本, https://downloads.teradata.com/download/database/teradata-express-for-vmware-player
Step 2 − 提取文件并指定目标文件夹。
Step 3 − 从以下链接下载 VMWare Workstation 播放器, https://my.vmware.com/web/vmware/downloads 。它适用于 Windows 和 Linux。下载适用于 Windows 的 VMWARE Workstation 播放器。
Step 4 − 下载完成后,安装软件。
Step 5 − 安装完成后,运行 VMWARE 客户端。
Step 6 − 选择“打开虚拟机”。浏览解压的 Teradata VMWare 文件夹并选择扩展名为 .vmdk 的文件。
Step 7 − Teradata VMWare 已添加到 VMWare 客户端。选择添加的 Teradata VMware 然后单击“播放虚拟机”。
Step 8 − 如果软件更新中弹出窗口,您可以选择“稍后提醒我”。
Step 9 − 输入用户名 root,按 tab 并输入密码 root,再次按 Enter。
Step 10 − 桌面出现以下屏幕后,双击“root 的主页”。然后双击“Genome 终端”。这将打开 Shell。
Step 11 − 在以下 shell 中,输入命令 /etc/init.d/tpa start。这将启动 Teradata 服务器。
Teradata - Architecture
Teradata 架构基于大规模并行处理 (MPP) 架构。Teradata 的主要组件有解析引擎、BYNET 和访问模块处理器 (AMP)。下图显示了 Teradata 节点的高层次架构。
Components of Teradata
Teradata 的关键组件如下所示 −
-
Node − 它是 Teradata 系统中的基本单元。Teradata 系统中的每个单独服务器称为一个节点。一个节点包含其自己的操作系统、CPU、内存、Teradata RDBMS 软件的副本和磁盘空间。一个机柜由一个或多个节点组成。
-
Parsing Engine − 解析引擎负责接收来自客户端的查询并准备一个高效的执行计划。解析引擎的职责有 −接收来自客户端的 SQL 查询解析 SQL 查询并检查语法错误检查用户是否对 SQL 查询中使用的对象拥有所需权限检查 SQL 中使用的对象是否实际存在准备执行计划以执行 SQL 查询并将其传递给 BYNET接收来自 AMP 的结果并发送给客户端
-
Message Passing Layer − 消息传递层称为 BYNET,它是 Teradata 系统中的网络层。它允许在 PE 和 AMP 之间以及在节点之间进行通信。它接收来自解析引擎的执行计划并发送给 AMP。同样,它接收来自 AMP 的结果并发送给解析引擎。
-
Access Module Processor (AMP) − AMP(称为虚拟处理器 (vprocs))实际上负责存储和检索数据。AMP 从解析引擎接收数据和执行计划,执行任何数据类型转换、聚合、筛选、排序并将数据存储在与它们关联的磁盘中。来自表的记录在系统中的 AMP 之间均匀分布。每个 AMP 都与存储数据的磁盘集相关联。只有该 AMP 可以读写磁盘中的数据。
Teradata - Relational Concepts
关系数据库管理系统 (RDBMS) 是一种 DBMS 软件,有助于与数据库交互。它们使用结构化查询语言 (SQL) 与存储在表中的数据交互。
Tables
表是 RDBMS 中存储数据的基本单位。表是行和列的集合。以下是 employee 表的示例。
EmployeeNo |
FirstName |
LastName |
BirthDate |
101 |
Mike |
James |
1/5/1980 |
104 |
Alex |
Stuart |
11/6/1984 |
102 |
Robert |
Williams |
3/5/1983 |
105 |
Robert |
James |
12/1/1984 |
103 |
Peter |
Paul |
4/1/1983 |
Columns
一列中包含类似的数据。例如,Employee 表中的列 BirthDate 包含所有员工的 birth_date 信息。
BirthDate |
1/5/1980 |
11/6/1984 |
3/5/1983 |
12/1/1984 |
4/1/1983 |
Teradata - Data Types
表中的每一行都与数据类型相关联。数据类型指定将存储在该列中的值类型。Teradata 支持多种数据类型。以下是一些常用的数据类型。
Data Types |
Length (Bytes) |
Range of values |
BYTEINT |
1 |
-128 to +127 |
SMALLINT |
2 |
-32768 to +32767 |
INTEGER |
4 |
-2,147,483,648 to +2147,483,647 |
BIGINT |
8 |
-9,233,372,036,854,775,80 8 到 +9,233,372,036,854,775,8 07 |
DECIMAL |
1-16 |
|
NUMERIC |
1-16 |
|
FLOAT |
8 |
IEEE format |
CHAR |
Fixed Format |
1-64,000 |
VARCHAR |
Variable |
1-64,000 |
DATE |
4 |
YYYYYMMDD |
TIME |
6 or 8 |
HHMMSS.nnnnnn or HHMMSS.nnnnnn+HHMM |
TIMESTAMP |
10 or 12 |
YYMMDDHHMMSS.nnnnnn or YYMMDDHHMMSS.nnnnnn +HHMM |
Teradata - Tables
关系模型中的表定义为数据的集合。它们表示为行和列。
Table Types
类型 Teradata 支持不同类型的表。
-
Permanent Table − 这是默认表,它包含用户插入的数据,并永久存储数据。
-
Volatile Table − 仅在用户会话期间保留插入易失表的数据。该表和数据在会话结束时被删除。这些表主要用于在数据转换期间保存中间数据。
-
Global Temporary Table − 全局临时表是持续的,但该表中的数据在用户会话结束时被删除。
-
Derived Table − 派生数据表拥有查询中的中间结果。这些表存在于用来创建、使用和删除它们的查询中。
Set Versus Multiset
Teradata 根据重复记录的处理方式将表分类为 SET 或 MULTISET 表。定义为 SET 表的表不存储重复记录,而 MULTISET 表则可以存储重复记录。
Sr.No |
Table Commands & Description |
1 |
Create Table Teradata 中使用 CREATE TABLE 命令来创建表。 |
2 |
Alter Table Teradata 中使用 ALTER TABLE 命令在现有表中添加或删除列。 |
3 |
Drop Table Teradata 中使用 DROP TABLE 命令来删除表。 |
Teradata - Data Manipulation
本章介绍用于处理存储在 Teradata 表中的数据的 SQL 命令。
Insert Records
INSERT INTO 语句用于向表中插入记录。
Syntax
以下是 INSERT INTO 的通用语法。
INSERT INTO <tablename>
(column1, column2, column3,…)
VALUES
(value1, value2, value3 …);
Example
以下示例向 employee 表中插入记录。
INSERT INTO Employee (
EmployeeNo,
FirstName,
LastName,
BirthDate,
JoinedDate,
DepartmentNo
)
VALUES (
101,
'Mike',
'James',
'1980-01-05',
'2005-03-27',
01
);
插入上述查询后,可以使用 SELECT 语句从表中查看记录。
EmployeeNo |
FirstName |
LastName |
JoinedDate |
DepartmentNo |
BirthDate |
101 |
Mike |
James |
3/27/2005 |
1 |
1/5/1980 |
Insert from Another Table
INSERT SELECT 语句用于从另一个表中插入记录。
Syntax
以下是 INSERT INTO 的通用语法。
INSERT INTO <tablename>
(column1, column2, column3,…)
SELECT
column1, column2, column3…
FROM
<source table>;
Example
以下示例向 employee 表中插入记录。在运行以下插入查询之前,创建一个名为 Employee_Bkup 的表,其列定义与 employee 表相同。
INSERT INTO Employee_Bkup (
EmployeeNo,
FirstName,
LastName,
BirthDate,
JoinedDate,
DepartmentNo
)
SELECT
EmployeeNo,
FirstName,
LastName,
BirthDate,
JoinedDate,
DepartmentNo
FROM
Employee;
执行上述查询时,将把 employee 表中的所有记录插入到 employee_bkup 表中。
Update Records
UPDATE 语句用于更新表中的记录。
Example
下面的示例将雇员 101 的员工部门更新为 03。
UPDATE Employee
SET DepartmentNo = 03
WHERE EmployeeNo = 101;
在下面的输出中,您可以看到雇员编号为 101 的部门编号从 1 更新为 3。
SELECT Employeeno, DepartmentNo FROM Employee;
*** Query completed. One row found. 2 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo DepartmentNo
----------- -------------
101 3
Teradata - SELECT Statement
SELECT 语句用于从表中检索记录。
Example
考虑以下员工表。
EmployeeNo |
FirstName |
LastName |
JoinedDate |
DepartmentNo |
BirthDate |
101 |
Mike |
James |
3/27/2005 |
1 |
1/5/1980 |
102 |
Robert |
Williams |
4/25/2007 |
2 |
3/5/1983 |
103 |
Peter |
Paul |
3/21/2007 |
2 |
4/1/1983 |
104 |
Alex |
Stuart |
2/1/2008 |
2 |
11/6/1984 |
105 |
Robert |
James |
1/4/2008 |
3 |
12/1/1984 |
下面是 SELECT 语句的一个示例。
SELECT EmployeeNo,FirstName,LastName
FROM Employee;
执行此查询时,它会从 employee 表中提取 EmployeeNo、FirstName 和 LastName 列。
EmployeeNo FirstName LastName
----------- ------------------------------ ---------------------------
101 Mike James
104 Alex Stuart
102 Robert Williams
105 Robert James
103 Peter Paul
如果您想提取表中的所有列,您可以使用以下命令,而不必列出所有列。
SELECT * FROM Employee;
上述查询将从 employee 表中提取所有记录。
Teradata - Logical and Conditional Operators
Teradata 支持以下逻辑和条件运算符。这些运算符用于执行比较并组合多个条件。
Syntax |
Meaning |
> |
Greater than |
< |
Less than |
>= |
大于或等于 |
⇐ |
小于或等于 |
= |
Equal to |
BETWEEN |
If values within range |
IN |
If values in <expression> |
NOT IN |
如果值不在 <expression> 中 |
IS NULL |
If value is NULL |
IS NOT NULL |
如果值不为 NULL |
AND |
组合多个条件。仅当所有条件都满足时才评估为真 |
OR |
组合多个条件。仅当任一条件满足时才评估为真。 |
NOT |
颠倒条件的含义 |
BETWEEN
BETWEEN 命令用于检查某个值是否在一个值范围内。
Example
考虑以下员工表。
EmployeeNo |
FirstName |
LastName |
JoinedDate |
DepartmentNo |
BirthDate |
101 |
Mike |
James |
3/27/2005 |
1 |
1/5/1980 |
102 |
Robert |
Williams |
4/25/2007 |
2 |
3/5/1983 |
103 |
Peter |
Paul |
3/21/2007 |
2 |
4/1/1983 |
104 |
Alex |
Stuart |
2/1/2008 |
2 |
11/6/1984 |
105 |
Robert |
James |
1/4/2008 |
3 |
12/1/1984 |
以下示例获取雇员编号在 101、102 和 103 之间的记录。
SELECT EmployeeNo, FirstName FROM
Employee
WHERE EmployeeNo BETWEEN 101 AND 103;
在执行上述查询时,它返回雇员编号在 101 和 103 之间的雇员记录。
*** Query completed. 3 rows found. 2 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo FirstName
----------- ------------------------------
101 Mike
102 Robert
103 Peter
IN
IN 命令用于针对给定的值列表检查值。
Example
以下示例获取雇员编号为 101、102 和 103 的记录。
SELECT EmployeeNo, FirstName FROM
Employee
WHERE EmployeeNo in (101,102,103);
上述查询返回以下记录。
*** Query completed. 3 rows found. 2 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo FirstName
----------- ------------------------------
101 Mike
102 Robert
103 Peter
NOT IN
NOT IN 命令颠倒了 IN 命令的结果。它获取与给定列表不匹配的值的记录。
Example
以下示例提取了不在 101、102 和 103 中的员工编号记录。
SELECT * FROM
Employee
WHERE EmployeeNo not in (101,102,103);
上述查询返回以下记录。
*** Query completed. 2 rows found. 6 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo FirstName LastName
----------- ------------------------------ -----------------------------
104 Alex Stuart
105 Robert James
Teradata - SET Operators
集合运算符结合了来自多个 SELECT 语句的结果。这可能看起来类似于联接,但联接合并了来自多个表的列,而集合运算符合并了来自多行中的行。
UNION
UNION 语句用于结合来自多个 SELECT 语句的结果。它忽略了重复项。
Syntax
以下是 UNION 语句的基本语法。
SELECT col1, col2, col3…
FROM
<table 1>
[WHERE condition]
UNION
SELECT col1, col2, col3…
FROM
<table 2>
[WHERE condition];
Example
考虑以下员工表和薪资表。
EmployeeNo |
FirstName |
LastName |
JoinedDate |
DepartmentNo |
BirthDate |
101 |
Mike |
James |
3/27/2005 |
1 |
1/5/1980 |
102 |
Robert |
Williams |
4/25/2007 |
2 |
3/5/1983 |
103 |
Peter |
Paul |
3/21/2007 |
2 |
4/1/1983 |
104 |
Alex |
Stuart |
2/1/2008 |
2 |
11/6/1984 |
105 |
Robert |
James |
1/4/2008 |
3 |
12/1/1984 |
EmployeeNo |
Gross |
Deduction |
NetPay |
101 |
40,000 |
4,000 |
36,000 |
102 |
80,000 |
6,000 |
74,000 |
103 |
90,000 |
7,000 |
83,000 |
104 |
75,000 |
5,000 |
70,000 |
以下 UNION 查询结合了 Employee 和 Salary 表中的 EmployeeNo 值。
SELECT EmployeeNo
FROM
Employee
UNION
SELECT EmployeeNo
FROM
Salary;
执行查询后,会产生以下输出。
EmployeeNo
-----------
101
102
103
104
105
UNION ALL
UNION ALL 语句类似于 UNION,它结合了来自多个表的包括重复行在内的结果。
INTERSECT
INTERSECT 命令也用于结合来自多个 SELECT 语句的结果。它返回了在第二个 SELECT 语句中具有对应匹配项的第一个 SELECT 语句中的行。换句话说,它返回了同时存在于这两个 SELECT 语句中的行。
Teradata - String Manipulation
Teradata 提供了多个函数来处理字符串。这些函数与 ANSI 标准兼容。
Sr.No |
String Function & Description |
1 |
* |
*Concatenates strings together |
|
2 |
*SUBSTR*提取字符串的一部分(Teradata 扩展) |
3 |
*SUBSTRING*提取字符串的一部分(ANSI 标准) |
4 |
*INDEX*定位字符串中字符的位置(Teradata 扩展) |
5 |
*POSITION*定位字符串中字符的位置(ANSI 标准) |
6 |
*TRIM*从字符串中修剪空格 |
7 |
*UPPER*将字符串转换为大写 |
8 |
*LOWER*将字符串转换为小写 |
Teradata - Date/Time Functions
本章讨论 Teradata 中提供的日期/时间函数。
Date Storage
日期使用以下公式在内部存储为整数。
((YEAR - 1900) * 10000) + (MONTH * 100) + DAY
您可以使用以下查询检查日期的存储方式。
SELECT CAST(CURRENT_DATE AS INTEGER);
由于日期存储为整数,因此您可以在日期上执行一些算术运算。Teradata 提供可执行这些运算的函数。
EXTRACT
EXTRACT 函数从 DATE 值中摘取日期、月份和年份的部分。该函数也用于从 TIME/TIMESTAMP 值中摘取小时、分钟和秒。
Example
以下示例显示如何从日期和时间戳值中摘取年份、月份、日期、小时、分钟和秒值。
SELECT EXTRACT(YEAR FROM CURRENT_DATE);
EXTRACT(YEAR FROM Date)
-----------------------
2016
SELECT EXTRACT(MONTH FROM CURRENT_DATE);
EXTRACT(MONTH FROM Date)
------------------------
1
SELECT EXTRACT(DAY FROM CURRENT_DATE);
EXTRACT(DAY FROM Date)
------------------------
1
SELECT EXTRACT(HOUR FROM CURRENT_TIMESTAMP);
EXTRACT(HOUR FROM Current TimeStamp(6))
---------------------------------------
4
SELECT EXTRACT(MINUTE FROM CURRENT_TIMESTAMP);
EXTRACT(MINUTE FROM Current TimeStamp(6))
-----------------------------------------
54
SELECT EXTRACT(SECOND FROM CURRENT_TIMESTAMP);
EXTRACT(SECOND FROM Current TimeStamp(6))
-----------------------------------------
27.140000
INTERVAL
Teradata 提供 INTERVAL 函数对 DATE 和 TIME 值执行算术运算。有两种类型的 INTERVAL 函数。
Day-Time Interval
-
DAY
-
DAY TO HOUR
-
DAY TO MINUTE
-
DAY TO SECOND
-
HOUR
-
HOUR TO MINUTE
-
HOUR TO SECOND
-
MINUTE
-
MINUTE TO SECOND
-
SECOND
Example
以下示例将 3 年添加到当前日期。
SELECT CURRENT_DATE, CURRENT_DATE + INTERVAL '03' YEAR;
Date (Date+ 3)
-------- ---------
16/01/01 19/01/01
以下示例将 3 年和 01 个月添加到当前日期。
SELECT CURRENT_DATE, CURRENT_DATE + INTERVAL '03-01' YEAR TO MONTH;
Date (Date+ 3-01)
-------- ------------
16/01/01 19/02/01
以下示例将 01 天、05 小时和 10 分钟添加到当前时间戳。
SELECT CURRENT_TIMESTAMP,CURRENT_TIMESTAMP + INTERVAL '01 05:10' DAY TO MINUTE;
Current TimeStamp(6) (Current TimeStamp(6)+ 1 05:10)
-------------------------------- --------------------------------
2016-01-01 04:57:26.360000+00:00 2016-01-02 10:07:26.360000+00:00
Teradata - Built-in Functions
Teradata 提供内置函数,这是对 SQL 的扩展。以下是常见的内置函数。
Function |
Result |
SELECT DATE; |
Date -------- 16/01/01 |
SELECT CURRENT_DATE; |
Date -------- 16/01/01 |
SELECT TIME; |
Time -------- 04:50:29 |
SELECT CURRENT_TIME; |
Time -------- 04:50:29 |
SELECT CURRENT_TIMESTAMP; |
Current TimeStamp(6) -------------------------------- 2016-01-01 04:51:06.990000+00:00 |
SELECT DATABASE; |
Database ------------------------------ TDUSER |
Teradata - Aggregate Functions
Teradata 支持常见的聚合函数。它们可以与 SELECT 语句一起使用。
-
COUNT − 计算行数
-
SUM − 对指定列的值求和
-
MAX − 返回指定列的最大值
-
MIN − 返回指定列的最小值
-
AVG − 返回指定列的平均值
Example
请考虑以下 Salary 表。
EmployeeNo |
Gross |
Deduction |
NetPay |
101 |
40,000 |
4,000 |
36,000 |
104 |
75,000 |
5,000 |
70,000 |
102 |
80,000 |
6,000 |
74,000 |
105 |
70,000 |
4,000 |
66,000 |
103 |
90,000 |
7,000 |
83,000 |
MIN
以下示例从 Salary 表中返回最低员工净薪水值。
SELECT min(NetPay) from Salary;
Minimum(NetPay)
---------------------
36000
Teradata - CASE and COALESCE
本章介绍 Teradata 的 CASE 和 COALESCE 函数。
CASE Expression
CASE 表达式针对条件或 WHEN 子句评估每一行,并返回第一次匹配的结果。如果没有匹配项,则返回 ELSE 部分的结果。
Syntax
以下是 CASE 表达式的语法。
CASE <expression>
WHEN <expression> THEN result-1
WHEN <expression> THEN result-2
ELSE
Result-n
END
Example
考虑以下 Employee 表。
EmployeeNo |
FirstName |
LastName |
JoinedDate |
DepartmentNo |
BirthDate |
101 |
Mike |
James |
3/27/2005 |
1 |
1/5/1980 |
102 |
Robert |
Williams |
4/25/2007 |
2 |
3/5/1983 |
103 |
Peter |
Paul |
3/21/2007 |
2 |
4/1/1983 |
104 |
Alex |
Stuart |
2/1/2008 |
2 |
11/6/1984 |
105 |
Robert |
James |
1/4/2008 |
3 |
12/1/1984 |
以下示例评估 DepartmentNo 列,如果部门编号为 1,则返回 1;如果部门编号为 3,则返回 2;否则,返回“无效部门”值。
SELECT
EmployeeNo,
CASE DepartmentNo
WHEN 1 THEN 'Admin'
WHEN 2 THEN 'IT'
ELSE 'Invalid Dept'
END AS Department
FROM Employee;
执行以上查询后,将产生以下输出。
*** Query completed. 5 rows found. 2 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo Department
----------- ------------
101 Admin
104 IT
102 IT
105 Invalid Dept
103 IT
上面的 CASE 表达式也可以写成以下形式,产生的结果与上面相同。
SELECT
EmployeeNo,
CASE
WHEN DepartmentNo = 1 THEN 'Admin'
WHEN DepartmentNo = 2 THEN 'IT'
ELSE 'Invalid Dept'
END AS Department
FROM Employee;
NULLIF
NULLIF 语句在参数相等时返回 NULL。
Example
以下示例在 DepartmentNo 等于 3 时返回 NULL。否则,返回 DepartmentNo 值。
SELECT
EmployeeNo,
NULLIF(DepartmentNo,3) AS department
FROM Employee;
以上查询返回以下记录。您可以看到员工 105 的部门号为 NULL。
*** Query completed. 5 rows found. 2 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo department
----------- ------------------
101 1
104 2
102 2
105 ?
103 2
Teradata - Primary Index
主键索引用于指定数据在 Teradata 中所在的位置。它用于指定哪个 AMP 获取数据行。Teradata 中的每个表格都需要定义一个主键索引。如果未定义主键索引,则 Teradata 会自动分配主键索引。主键索引提供了访问数据的最快速方式。主键最多可以有 64 列。
主键索引在创建表格时定义。主键索引有 2 种类型。
-
Unique Primary Index(UPI)
-
Non Unique Primary Index(NUPI)
Non Unique Primary Index (NUPI)
如果将表格定义为具有 NUPI,则被视为 UPI 的列可以接受重复值。
Create Non Unique Primary Index
以下示例创建员工帐户表格,其列 EmployeeNo 为非唯一主键索引。EmployeeNo 定义为非唯一主键索引,因为一名员工可以在表格中拥有多个帐户:一个用于薪资帐户,另一个用于报销帐户。
CREATE SET TABLE Employee _Accounts (
EmployeeNo INTEGER,
employee_bank_account_type BYTEINT.
employee_bank_account_number INTEGER,
employee_bank_name VARCHAR(30),
employee_bank_city VARCHAR(30)
)
PRIMARY INDEX(EmployeeNo);
Teradata - Joins
Join 用于将来自多张表的数据记录组合在一起。表是根据这些表中公共栏位/值相连接的。
有不同类型的 Join 可用。
-
Inner Join
-
Left Outer Join
-
Right Outer Join
-
Full Outer Join
-
Self Join
-
Cross Join
-
Cartesian Production Join
INNER JOIN
Inner Join 组合来自多张表的数据记录,并返回同时存在于这两张表中的值。
Syntax
以下是 INNER JOIN 语句的语法。
SELECT col1, col2, col3….
FROM
Table-1
INNER JOIN
Table-2
ON (col1 = col2)
<WHERE condition>;
Example
考虑以下员工表和薪资表。
EmployeeNo |
FirstName |
LastName |
JoinedDate |
DepartmentNo |
BirthDate |
101 |
Mike |
James |
3/27/2005 |
1 |
1/5/1980 |
102 |
Robert |
Williams |
4/25/2007 |
2 |
3/5/1983 |
103 |
Peter |
Paul |
3/21/2007 |
2 |
4/1/1983 |
104 |
Alex |
Stuart |
2/1/2008 |
2 |
11/6/1984 |
105 |
Robert |
James |
1/4/2008 |
3 |
12/1/1984 |
EmployeeNo |
Gross |
Deduction |
NetPay |
101 |
40,000 |
4,000 |
36,000 |
102 |
80,000 |
6,000 |
74,000 |
103 |
90,000 |
7,000 |
83,000 |
104 |
75,000 |
5,000 |
70,000 |
以下查询在公共栏位 EmployeeNo 上连接 Employee 表和 Salary 表。每个表都被赋予别名 A 和 B,并且栏位使用正确的别名进行引用。
SELECT A.EmployeeNo, A.DepartmentNo, B.NetPay
FROM
Employee A
INNER JOIN
Salary B
ON (A.EmployeeNo = B. EmployeeNo);
当执行以上查询时,将会返回以下记录。员工 105 未包含在结果中,因为它在 Salary 表中没有匹配的记录。
*** Query completed. 4 rows found. 3 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo DepartmentNo NetPay
----------- ------------ -----------
101 1 36000
102 2 74000
103 2 83000
104 2 70000
OUTER JOIN
LEFT OUTER JOIN 和 RIGHT OUTER JOIN 也合并来自多张表的结果。
-
LEFT OUTER JOIN 返回来自左表的全部记录,并且仅返回来自右表的匹配记录。
-
RIGHT OUTER JOIN 返回来自右表的全部记录,并且仅返回来自左表的匹配记录。
-
FULL OUTER JOIN 组合来自 LEFT OUTER 和 RIGHT OUTER JOIN 的结果。它返回来自联结表的匹配记录和不匹配记录。
Syntax
以下为 OUTER JOIN 语句的语法。你需要使用 LEFT OUTER JOIN、RIGHT OUTER JOIN 或 FULL OUTER JOIN 中的一个选项。
SELECT col1, col2, col3….
FROM
Table-1
LEFT OUTER JOIN/RIGHT OUTER JOIN/FULL OUTER JOIN
Table-2
ON (col1 = col2)
<WHERE condition>;
Example
考虑以下 LEFT OUTER JOIN 查询示例。它返回 Employee 表中的所有记录以及 Salary 表中的匹配记录。
SELECT A.EmployeeNo, A.DepartmentNo, B.NetPay
FROM
Employee A
LEFT OUTER JOIN
Salary B
ON (A.EmployeeNo = B. EmployeeNo)
ORDER BY A.EmployeeNo;
当执行以上查询时,将生成以下输出。对于员工 105,NetPay 值为 NULL,因为它在 Salary 表中没有匹配的记录。
*** Query completed. 5 rows found. 3 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo DepartmentNo NetPay
----------- ------------ -----------
101 1 36000
102 2 74000
103 2 83000
104 2 70000
105 3 ?
CROSS JOIN
Cross Join 将左表中的每行与右表中的每行进行连接。
Syntax
以下是 CROSS JOIN 语句的语法。
SELECT A.EmployeeNo, A.DepartmentNo, B.EmployeeNo,B.NetPay
FROM
Employee A
CROSS JOIN
Salary B
WHERE A.EmployeeNo = 101
ORDER BY B.EmployeeNo;
执行上述查询时,将得到以下输出。将 Employee 表中的员工编号 101 与 Salary 表中的每一条记录联接。
*** Query completed. 4 rows found. 4 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo DepartmentNo EmployeeNo NetPay
----------- ------------ ----------- -----------
101 1 101 36000
101 1 104 70000
101 1 102 74000
101 1 103 83000
Teradata - SubQueries
子查询基于其他表中的值从一个表中返回记录。它是另一个查询中的 SELECT 查询。称为内部查询的 SELECT 查询首先执行,而结果则由外部查询使用。其一些显著特征:
-
查询可以有多个子查询,并且子查询可以包含其他子查询。
-
子查询不返回重复的记录。
-
如果子查询仅返回一个值,则可以使用 = 运算符将其与外部查询一起使用。如果它返回多个值,则可以使用 IN 或 NOT IN。
Syntax
以下是子查询的通用语法。
SELECT col1, col2, col3,…
FROM
Outer Table
WHERE col1 OPERATOR ( Inner SELECT Query);
Example
考虑以下 Salary 表格。
EmployeeNo |
Gross |
Deduction |
NetPay |
101 |
40,000 |
4,000 |
36,000 |
102 |
80,000 |
6,000 |
74,000 |
103 |
90,000 |
7,000 |
83,000 |
104 |
75,000 |
5,000 |
70,000 |
以下查询标识出具有最高工资的员工编号。内部 SELECT 执行聚合函数以返回最大的 NetPay 值,而外部 SELECT 查询使用此值返回具有此值的员工记录。
SELECT EmployeeNo, NetPay
FROM Salary
WHERE NetPay =
(SELECT MAX(NetPay)
FROM Salary);
执行此查询时,将得到以下输出。
*** Query completed. One row found. 2 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo NetPay
----------- -----------
103 83000
Teradata - Table Types
Teradata 支持以下表格类型来保存临时数据。
-
Derived Table
-
Volatile Table
-
Global Temporary Table
Derived Table
导出表在查询中创建、使用和删除。它们用于在查询中存储中间结果。
Example
以下示例使用工资超过 75000 的员工记录构建了导出表 EmpSal。
SELECT
Emp.EmployeeNo,
Emp.FirstName,
Empsal.NetPay
FROM
Employee Emp,
(select EmployeeNo , NetPay
from Salary
where NetPay >= 75000) Empsal
where Emp.EmployeeNo = Empsal.EmployeeNo;
当执行以上查询时,它将返回工资超过 75000 的员工。
*** Query completed. One row found. 3 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo FirstName NetPay
----------- ------------------------------ -----------
103 Peter 83000
Volatile Table
易失表在用户会话中创建、使用和删除。它们的定义未存储在数据字典中。它们保存查询中经常使用的中间数据。以下是语法。
Teradata - Space Concepts
Teradata 中有三种类型的空间可用。
Permanent Space
永久空间是用户/数据库可用于保存数据行的最大可用空间。永久表、日记、回退表和辅助索引子表使用永久空间。
永久空间不会预先分配给数据库/用户。它们仅被定义为数据库/用户可以使用的最大空间量。永久空间的数量将除以 AMP 的数量。每当 AMP 限制超过时,就会生成一个错误消息。
Teradata - Secondary Index
表只能包含一个主键索引。更常见的是,您将遇到表包含其他列的情况,其中使用经常访问数据。Teradata 将对这些查询执行全表扫描。辅助索引解决了此问题。
辅助索引是访问数据的替代路径。主键索引与辅助索引之间存在一些差异。
-
辅助索引不参与数据分布。
-
辅助索引值存储在子表中。这些表内置于所有 AMP 中。
-
Secondary indexes are optional.
-
它们可以在创建表时或创建表后创建。
-
由于构建子表并使用它,它们占用额外空间,并且由于需要为每一行更新子表,它们还需要维护。
有两种类型的二级索引 -
-
Unique Secondary Index (USI)
-
Non-Unique Secondary Index (NUSI)
Teradata - Statistics
Teradata 优化器会针对每个 SQL 查询提出执行策略。此执行策略基于在 SQL 查询所用表中收集的统计信息。使用 COLLECT STATISTICS 命令收集表的统计信息。优化器需要环境信息和数据人口统计信息来提出最佳执行策略。
Data Demographics
-
Number of rows
-
Row size
-
表中的值范围
-
每个值的行数
-
Number of Nulls
有三种方法可用于收集表中的统计信息。
-
Random AMP Sampling
-
Full statistics collection
-
Using SAMPLE option
Collecting Statistics
COLLECT STATISTICS 命令用于收集表中的统计信息。
Teradata - Compression
压缩用于减少表格使用的存储空间。在 Teradata 中,压缩可以压缩 255 个不同的值,包括 NULL。由于存储减少,因此 Teradata 可以在一个块中存储更多的记录。由于每个 I/O 操作可以处理每个块中的更多行,因此这将改善查询响应时间。可以在创建表格时使用 CREATE TABLE 添加压缩,或在创建表格后使用 ALTER TABLE 命令添加压缩。
Multi-Value Compression (MVC)
下表将字段 DepatmentNo 压缩为值 1、2 和 3。当压缩应用于某一列时,该列的值不会与该行存储在一起。而是这些值存储在每个 AMP 的表头中,并且只添加表示值到行中的存在位。
CREATE SET TABLE employee (
EmployeeNo integer,
FirstName CHAR(30),
LastName CHAR(30),
BirthDate DATE FORMAT 'YYYY-MM-DD-',
JoinedDate DATE FORMAT 'YYYY-MM-DD-',
employee_gender CHAR(1),
DepartmentNo CHAR(02) COMPRESS(1,2,3)
)
UNIQUE PRIMARY INDEX(EmployeeNo);
多值压缩可用于处理包含有限值的大表中的列。
Teradata - Explain
EXPLAIN 命令以英语返回解析引擎的执行计划。它可以与任何 SQL 语句一起使用,但不能与另一个 EXPLAIN 命令一起使用。当查询以 EXPLAIN 命令开头时,解析引擎的执行计划将返回给用户,而不是 AMP。
Examples of EXPLAIN
考虑以下定义的 Employee 表。
CREATE SET TABLE EMPLOYEE,FALLBACK (
EmployeeNo INTEGER,
FirstName VARCHAR(30),
LastName VARCHAR(30),
DOB DATE FORMAT 'YYYY-MM-DD',
JoinedDate DATE FORMAT 'YYYY-MM-DD',
DepartmentNo BYTEINT
)
UNIQUE PRIMARY INDEX ( EmployeeNo );
下面给出了一些 EXPLAIN 计划示例。
Full Table Scan (FTS)
当 SELECT 语句中未指定条件时,优化器可能会选择使用全表扫描,在该扫描中将访问表中的每一行。
Example
以下是优化器可能选择 FTS 的示例查询。
EXPLAIN SELECT * FROM employee;
当执行以上查询时,它将生成以下输出。可以看出,优化器选择访问所有 AMP 和 AMP 中的所有行。
1) First, we lock a distinct TDUSER."pseudo table" for read on a
RowHash to prevent global deadlock for TDUSER.employee.
2) Next, we lock TDUSER.employee for read.
3) We do an all-AMPs RETRIEVE step from TDUSER.employee by way of an
all-rows scan with no residual conditions into Spool 1
(group_amps), which is built locally on the AMPs. The size of
Spool 1 is estimated with low confidence to be 2 rows (116 bytes).
The estimated time for this step is 0.03 seconds.
4) 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 is 0.03 seconds.
Unique Primary Index
当使用唯一的主索引访问行时,则是一个 AMP 操作。
EXPLAIN SELECT * FROM employee WHERE EmployeeNo = 101;
当执行以上查询时,它将生成以下输出。可以看到,这是一个单 AMP 检索,并且优化器正在使用唯一的主索引来访问行。
1) First, we do a single-AMP RETRIEVE step from TDUSER.employee by
way of the unique primary index "TDUSER.employee.EmployeeNo = 101"
with no residual conditions. The estimated time for this step is
0.01 seconds.
→ The row is sent directly back to the user as the result of
statement 1. The total estimated time is 0.01 seconds.
Unique Secondary Index
当使用唯一辅助索引访问行时,这是一个两安操作。
Example
查看如下定义的表“薪资”。
CREATE SET TABLE SALARY,FALLBACK (
EmployeeNo INTEGER,
Gross INTEGER,
Deduction INTEGER,
NetPay INTEGER
)
PRIMARY INDEX ( EmployeeNo )
UNIQUE INDEX (EmployeeNo);
查看以下 SELECT 语句。
EXPLAIN SELECT * FROM Salary WHERE EmployeeNo = 101;
当执行上述查询时,会生成以下输出。正如可以看到的那样,优化器使用唯一的辅助索引在两安操作中检索行。
1) First, we do a two-AMP RETRIEVE step from TDUSER.Salary
by way of unique index # 4 "TDUSER.Salary.EmployeeNo =
101" with no residual conditions. The estimated time for this
step is 0.01 seconds.
→ The row is sent directly back to the user as the result of
statement 1. The total estimated time is 0.01 seconds.
Additional Terms
以下是 EXPLAIN 计划中常见的术语列表。
… (Last Use) …
不再需要暂存文件,并且在完成此步骤时将释放该文件。
… with no residual conditions …
所有适用的条件都已应用于行。
… END TRANSACTION …
释放事务锁,并且提交更改。
… eliminating duplicate rows …
仅在暂存文件中存在重复行,不存在集合表中。执行 DISTINCT 操作。
… by way of a traversal of index #n extracting row ids only …
构建一个包含在辅助索引(索引 #n)中找到的行 ID 的暂存文件。
… we do a SMS (set manipulation step) …
使用 UNION、MINUS 或 INTERSECT 运算符组合行。
… which is redistributed by hash code to all AMPs.
在准备联接时重新分发数据。
… which is duplicated on all AMPs.
复制更小表(根据 SPOOL)中数据以准备进行联接。
… (one_AMP) or (group_AMPs)
指明将使用一个 AMP 或 AMP 子集而不是全部 AMP。
Teradata - Hashing Algorithm
行是根据主键值分配给特定 AMP 的。Teradata 使用哈希算法来确定哪一个 AMP 获取行。
以下是有关哈希算法的高级图表。
以下是插入数据的步骤。
-
客户端提交查询。
-
解析器接收查询并将记录的 PI 值传递给哈希算法。
-
哈希算法对主键值进行哈希处理,并返回一个称为行哈希的 32 位数字。
-
行哈希的高位(前 16 位)用于标识哈希映射条目。哈希映射包含一个 AMP #。哈希映射是一个包含特定 AMP # 的存储桶数组。
-
BYNET 将数据发送到已识别的 AMP。
-
AMP 使用 32 位行哈希定位磁盘中的行。
-
如果存在具有相同行哈希的任何记录,则它会增加唯一性 ID(一个 32 位数字)。对于新的行哈希,唯一性 ID 被分配为 1,并且每当插入具有相同行哈希的记录时都会增加 1。
-
行哈希和唯一性 ID 的组合称为行 ID。
-
行 ID 为磁盘中的每条记录添加前缀。
-
AMP 中的每一行表格都按其行 ID 逻辑排序。
How Tables are Stored
表格按其行 ID(行哈希 + 唯一性 ID)排序,然后存储在 AMP 中。行 ID 与每行数据一起存储。
Row Hash |
Uniqueness ID |
EmployeeNo |
FirstName |
LastName |
2A01 2611 |
0000 0001 |
101 |
Mike |
James |
2A01 2612 |
0000 0001 |
104 |
Alex |
Stuart |
2A01 2613 |
0000 0001 |
102 |
Robert |
Williams |
2A01 2614 |
0000 0001 |
105 |
Robert |
James |
2A01 2615 |
0000 0001 |
103 |
Peter |
Paul |
Teradata - JOIN Index
JOIN INDEX 是物化视图。其定义永久存储,每当关联索引中引用的基础表更新时数据都会更新。JOIN INDEX 可能包含一个或多个表,并且还包含预聚合数据。连接索引主要用于提高性能。
有不同类型的 join 索引可用。
-
单表连接索引 (STJI)
-
多表连接索引 (MTJI)
-
Aggregated Join Index (AJI)
Single Table Join Index
单表连接索引允许基于不同于基础表的主索引列对大表进行分区。
Example
考虑以下 Employee 和 Salary 表。
CREATE SET TABLE EMPLOYEE,FALLBACK (
EmployeeNo INTEGER,
FirstName VARCHAR(30) ,
LastName VARCHAR(30) ,
DOB DATE FORMAT 'YYYY-MM-DD',
JoinedDate DATE FORMAT 'YYYY-MM-DD',
DepartmentNo BYTEINT
)
UNIQUE PRIMARY INDEX ( EmployeeNo );
CREATE SET TABLE SALARY,FALLBACK (
EmployeeNo INTEGER,
Gross INTEGER,
Deduction INTEGER,
NetPay INTEGER
)
PRIMARY INDEX ( EmployeeNo )
UNIQUE INDEX (EmployeeNo);
以下是一个示例,在 Employee 表上创建名为 Employee_JI 的连接索引。
CREATE JOIN INDEX Employee_JI
AS
SELECT EmployeeNo,FirstName,LastName,
BirthDate,JoinedDate,DepartmentNo
FROM Employee
PRIMARY INDEX(FirstName);
如果用户提交一个带有 EmployeeNo 的 WHERE 子句的查询,那么系统将使用唯一主索引对 Employee 表进行查询。如果用户使用 employee_name 对 employee 表进行查询,那么系统可能会使用 employee_name 访问关联索引 Employee_JI。连接索引的行在 employee_name 列上进行哈希处理。如果没有定义连接索引,并且 employee_name 未定义为二级索引,那么系统将执行全表扫描以访问耗时的行。
您可以运行以下 EXPLAIN 计划并验证优化器计划。在以下示例中,您会看到优化器在使用 Employee_Name 列查询表时使用连接索引而不是基础 Employee 表。
EXPLAIN SELECT * FROM EMPLOYEE WHERE FirstName='Mike';
*** Help information returned. 8 rows.
*** Total elapsed time was 1 second.
Explanation
------------------------------------------------------------------------
1) First, we do a single-AMP RETRIEVE step from EMPLOYEE_JI by
way of the primary index "EMPLOYEE_JI.FirstName = 'Mike'"
with no residual conditions into Spool 1 (one-amp), which is built
locally on that AMP. The size of Spool 1 is estimated with low
confidence to be 2 rows (232 bytes). The estimated time for this
step is 0.02 seconds.
→ The contents of Spool 1 are sent back to the user as the result of
statement 1. The total estimated time is 0.02 seconds.
Multi Table Join Index
多表连接索引通过连接多张表来创建。多表连接索引可用于存储常用连接表的 result 集,以提高性能。
Example
以下示例通过连接 Employee 和 Salary 表创建名为 Employee_Salary_JI 的 JOIN INDEX。
CREATE JOIN INDEX Employee_Salary_JI
AS
SELECT a.EmployeeNo,a.FirstName,a.LastName,
a.BirthDate,a.JoinedDate,a.DepartmentNo,b.Gross,b.Deduction,b.NetPay
FROM Employee a
INNER JOIN Salary b
ON(a.EmployeeNo = b.EmployeeNo)
PRIMARY INDEX(FirstName);
每当更新基础表 Employee 或 Salary 时,连接索引 Employee_Salary_JI 也会自动更新。如果您正在运行一个连接 Employee 和 Salary 表的查询,那么优化器可能会选择直接从 Employee_Salary_JI 访问数据,而不是连接表。可以对查询使用 EXPLAIN 计划来验证优化器是否会选择基础表或连接索引。
Teradata - Views
视图是通过查询构建的数据库对象。视图可以使用单个表或通过连接使用多个表构建。其定义永久存储在数据字典中,但它们不会存储数据的副本。视图的数据是动态构建的。
视图可能包含表的子行集或表的子列集。
Create a View
使用 CREATE VIEW 语句创建视图。
Example
考虑以下 Employee 表。
EmployeeNo |
FirstName |
LastName |
BirthDate |
101 |
Mike |
James |
1/5/1980 |
104 |
Alex |
Stuart |
11/6/1984 |
102 |
Robert |
Williams |
3/5/1983 |
105 |
Robert |
James |
12/1/1984 |
103 |
Peter |
Paul |
4/1/1983 |
以下示例在 Employee 表上创建了一个视图。
CREATE VIEW Employee_View
AS
SELECT
EmployeeNo,
FirstName,
LastName,
FROM
Employee;
Using Views
您可以使用常规 SELECT 语句从视图中检索数据。
Example
以下示例从 Employee_View 中检索记录;
SELECT EmployeeNo, FirstName, LastName FROM Employee_View;
执行以上查询后,将产生以下输出。
*** Query completed. 5 rows found. 3 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo FirstName LastName
----------- ------------------------------ ---------------------------
101 Mike James
104 Alex Stuart
102 Robert Williams
105 Robert James
103 Peter Paul
Teradata - Macros
宏是一组 SQL 语句,它们通过调用宏名称来存储和执行。宏的定义存储在数据字典中。用户只需要 EXEC 权限来执行宏。用户不需要对宏中使用的数据库对象有单独的权限。宏语句作为单个事务执行。如果宏中的一个 SQL 语句失败,那么所有语句都会回滚。宏可以接受参数。宏可以包含 DDL 语句,但该语句应为宏中的最后一条语句。
Create Macros
使用 CREATE MACRO 语句创建宏。
Syntax
以下为 CREATE MACRO 命令的通用语法。
CREATE MACRO <macroname> [(parameter1, parameter2,...)] (
<sql statements>
);
Example
考虑以下 Employee 表。
EmployeeNo |
FirstName |
LastName |
BirthDate |
101 |
Mike |
James |
1/5/1980 |
104 |
Alex |
Stuart |
11/6/1984 |
102 |
Robert |
Williams |
3/5/1983 |
105 |
Robert |
James |
12/1/1984 |
103 |
Peter |
Paul |
4/1/1983 |
以下示例创建了一个名为 Get_Emp 的宏。它包含一个 select 语句以从员工表中检索记录。
CREATE MACRO Get_Emp AS (
SELECT
EmployeeNo,
FirstName,
LastName
FROM
employee
ORDER BY EmployeeNo;
);
Executing Macros
使用 EXEC 命令执行宏。
Example
以下示例执行名为 Get_Emp 的宏;当执行以下命令时,它会从员工表中检索所有记录。
EXEC Get_Emp;
*** Query completed. 5 rows found. 3 columns returned.
*** Total elapsed time was 1 second.
EmployeeNo FirstName LastName
----------- ------------------------------ ---------------------------
101 Mike James
102 Robert Williams
103 Peter Paul
104 Alex Stuart
105 Robert James
Parameterized Macros
Teradata 宏可以接受参数。在宏中,这些参数用 ;(分号)引用。
以下是接受参数的宏示例。
CREATE MACRO Get_Emp_Salary(EmployeeNo INTEGER) AS (
SELECT
EmployeeNo,
NetPay
FROM
Salary
WHERE EmployeeNo = :EmployeeNo;
);
Teradata - Stored Procedure
存储过程包含一组 SQL 语句和过程语句。它们可能仅包含过程语句。存储过程的定义存储在数据库中,并且参数存储在数据字典表中。
Creating Procedure
存储过程使用 CREATE PROCEDURE 语句创建。
Syntax
以下是 CREATE PROCEDURE 语句的通用语法。
CREATE PROCEDURE <procedurename> ( [parameter 1 data type, parameter 2 data type..] )
BEGIN
<SQL or SPL statements>;
END;
Example
请考虑以下 Salary 表。
EmployeeNo |
Gross |
Deduction |
NetPay |
101 |
40,000 |
4,000 |
36,000 |
102 |
80,000 |
6,000 |
74,000 |
103 |
90,000 |
7,000 |
83,000 |
104 |
75,000 |
5,000 |
70,000 |
以下示例创建了一个名为 InsertSalary 的存储过程以接受值并将其插入 Salary 表中。
CREATE PROCEDURE InsertSalary (
IN in_EmployeeNo INTEGER, IN in_Gross INTEGER,
IN in_Deduction INTEGER, IN in_NetPay INTEGER
)
BEGIN
INSERT INTO Salary (
EmployeeNo,
Gross,
Deduction,
NetPay
)
VALUES (
:in_EmployeeNo,
:in_Gross,
:in_Deduction,
:in_NetPay
);
END;
Teradata - JOIN strategies
本章讨论 Teradata 中可用的各种 JOIN 策略。
Merge Join
当连接基于相等条件时,将执行 Merge Join 方法。Merge Join 要求连接的行位于同一 AMP 上。行是根据其行哈希连接的。Merge Join 使用不同的连接策略将行带到同一个 AMP。
Strategy
如果连接列是相应表的初级索引,那么连接行已经位于同一个 AMP 上。在这种情况下,不需要分配。
考虑以下员工和薪水表。
CREATE SET TABLE EMPLOYEE,FALLBACK (
EmployeeNo INTEGER,
FirstName VARCHAR(30) ,
LastName VARCHAR(30) ,
DOB DATE FORMAT 'YYYY-MM-DD',
JoinedDate DATE FORMAT 'YYYY-MM-DD',
DepartmentNo BYTEINT
)
UNIQUE PRIMARY INDEX ( EmployeeNo );
CREATE SET TABLE Salary (
EmployeeNo INTEGER,
Gross INTEGER,
Deduction INTEGER,
NetPay INTEGER
)
UNIQUE PRIMARY INDEX(EmployeeNo);
当这两个表按 EmployeeNo 列连接时,则不会发生重新分配,因为 EmployeeNo 是被连接的两个表的初级索引。
Strategy
考虑以下员工和部门表。
CREATE SET TABLE EMPLOYEE,FALLBACK (
EmployeeNo INTEGER,
FirstName VARCHAR(30) ,
LastName VARCHAR(30) ,
DOB DATE FORMAT 'YYYY-MM-DD',
JoinedDate DATE FORMAT 'YYYY-MM-DD',
DepartmentNo BYTEINT
)
UNIQUE PRIMARY INDEX ( EmployeeNo );
CREATE SET TABLE DEPARTMENT,FALLBACK (
DepartmentNo BYTEINT,
DepartmentName CHAR(15)
)
UNIQUE PRIMARY INDEX ( DepartmentNo );
如果这两个表按 DeparmentNo 列连接,那么需要重新分配这些行,因为 DepartmentNo 是一个表中的初级索引,而另一个表中的非初级索引。在此场景中,连接行可能不在同一个 AMP 上。在这种情况下,Teradata 可能会在 DepartmentNo 列上重新分配员工表。
Teradata - Partitioned Primary Index
分区主索引 (PPI) 是一种索引机制,可用于提高某些查询的性能。当行插入表中时,它们会存储在 AMP 中,并按其行哈希顺序排列。当使用 PPI 定义表时,行会按其分区号排序。在每个分区内,它们会按行哈希排列。行会根据定义的分区表达式分配给分区。
Example
考虑具有订单号为主索引的如下订单表。
StoreNo |
OrderNo |
OrderDate |
OrderTotal |
101 |
7501 |
2015-10-01 |
900 |
101 |
7502 |
2015-10-02 |
1,200 |
102 |
7503 |
2015-10-02 |
3,000 |
102 |
7504 |
2015-10-03 |
2,454 |
101 |
7505 |
2015-10-03 |
1201 |
103 |
7506 |
2015-10-04 |
2,454 |
101 |
7507 |
2015-10-05 |
1201 |
101 |
7508 |
2015-10-05 |
1201 |
假设记录如以下表格所示在 AMP 之间进行分配。记录存储在 AMP 中,根据其行哈希进行排序。
**
RowHash |
OrderNo |
OrderDate |
1 |
7505 |
2015-10-03 |
2 |
7504 |
2015-10-03 |
3 |
7501 |
2015-10-01 |
4 |
7508 |
2015-10-05 |
**
RowHash |
OrderNo |
OrderDate |
1 |
7507 |
2015-10-05 |
2 |
7502 |
2015-10-02 |
3 |
7506 |
2015-10-04 |
4 |
7503 |
2015-10-02 |
如果您运行一个查询以提取某个特定日期的订单,则优化器可能会选择使用全表扫描,然后访问 AMP 中的所有记录。为了避免这种情况,您可以将订单日期定义为分区主索引。当行插入订单表时,它们按订单日期分区。它们将在每个分区中按其行哈希进行排序。
以下数据显示了如果按订单日期分区,记录如何存储在 AMP 中。如果运行一个查询以按订单日期访问记录,则只会访问包含特定订单记录的分区。
**
Partition |
RowHash |
OrderNo |
OrderDate |
0 |
3 |
7501 |
2015-10-01 |
1 |
1 |
7505 |
2015-10-03 |
1 |
2 |
7504 |
2015-10-03 |
2 |
4 |
7508 |
2015-10-05 |
**
Partition |
RowHash |
OrderNo |
OrderDate |
0 |
2 |
7502 |
2015-10-02 |
0 |
4 |
7503 |
2015-10-02 |
1 |
3 |
7506 |
2015-10-04 |
2 |
1 |
7507 |
2015-10-05 |
以下是一个带分区主索引创建表的示例。PARTITION BY 子句用于定义分区。
CREATE SET TABLE Orders (
StoreNo SMALLINT,
OrderNo INTEGER,
OrderDate DATE FORMAT 'YYYY-MM-DD',
OrderTotal INTEGER
)
PRIMARY INDEX(OrderNo)
PARTITION BY RANGE_N (
OrderDate BETWEEN DATE '2010-01-01' AND '2016-12-31' EACH INTERVAL '1' DAY
);
在上述示例中,该表按 OrderDate 列分区。每一天将会有一个单独的分区。
Teradata - OLAP Functions
OLAP 函数与聚合函数类似,只不过聚合函数仅返回一个值,而 OLAP 函数将提供各个行和聚合。
Syntax
以下是 OLAP 函数的一般语法。
<aggregate function> OVER
([PARTITION BY] [ORDER BY columnname][ROWS BETWEEN
UNBOUDED PRECEDING AND UNBOUNDED FOLLOWING)
聚合函数可以是 SUM、COUNT、MAX、MIN、AVG。
Example
考虑以下 Salary 表格。
EmployeeNo |
Gross |
Deduction |
NetPay |
101 |
40,000 |
4,000 |
36,000 |
102 |
80,000 |
6,000 |
74,000 |
103 |
90,000 |
7,000 |
83,000 |
104 |
75,000 |
5,000 |
70,000 |
以下是一个在 Salary 表格上查找 NetPay 的累积和或运行总和的示例。记录按 EmployeeNo 排序,并在 NetPay 列上计算累积和。
SELECT
EmployeeNo, NetPay,
SUM(Netpay) OVER(ORDER BY EmployeeNo ROWS
UNBOUNDED PRECEDING) as TotalSalary
FROM Salary;
执行以上查询后,将产生以下输出。
EmployeeNo NetPay TotalSalary
----------- ----------- -----------
101 36000 36000
102 74000 110000
103 83000 193000
104 70000 263000
105 18000 281000
RANK
RANK 函数根据提供的列对记录进行排序。RANK 函数还可以根据排名过滤返回的记录数。
Example
考虑以下 Employee 表。
EmployeeNo |
FirstName |
LastName |
JoinedDate |
DepartmentID |
BirthDate |
101 |
Mike |
James |
3/27/2005 |
1 |
1/5/1980 |
102 |
Robert |
Williams |
4/25/2007 |
2 |
3/5/1983 |
103 |
Peter |
Paul |
3/21/2007 |
2 |
4/1/1983 |
104 |
Alex |
Stuart |
2/1/2008 |
2 |
11/6/1984 |
105 |
Robert |
James |
1/4/2008 |
3 |
12/1/1984 |
下面的查询按加入日期对员工表中的记录排序,并按加入日期分配排名。
SELECT EmployeeNo, JoinedDate,RANK()
OVER(ORDER BY JoinedDate) as Seniority
FROM Employee;
执行以上查询后,将产生以下输出。
EmployeeNo JoinedDate Seniority
----------- ---------- -----------
101 2005-03-27 1
103 2007-03-21 2
102 2007-04-25 3
105 2008-01-04 4
104 2008-02-01 5
PARTITION BY 子句按 PARTITION BY 子句中定义的列对数据进行分组,并在每个组内执行 OLAP 函数。下面是使用 PARTITION BY 子句的查询示例。
SELECT EmployeeNo, JoinedDate,RANK()
OVER(PARTITION BY DeparmentNo ORDER BY JoinedDate) as Seniority
FROM Employee;
执行上述查询时,它会产生以下输出。可以看到每个部门的排名都已重置。
EmployeeNo DepartmentNo JoinedDate Seniority
----------- ------------ ---------- -----------
101 1 2005-03-27 1
103 2 2007-03-21 1
102 2 2007-04-25 2
104 2 2008-02-01 3
105 3 2008-01-04 1
Teradata - Data Protection
本章介绍了 Teradata 中提供的用于数据保护的功能。
Transient Journal
Teradata 使用临时日志来防止事务失败导致的数据丢失。每当运行任何事务时,临时日志都会保留受影响行的映像副本,直到事务成功或成功回滚为止。然后,将丢弃之前的映像。临时日志保存在每个 AMP 中。这是一个自动过程,并且无法禁用。
Fallback
备用保护通过在另一个称为备用 AMP 的 AMP 上存储表的第二行副本来保护表数据。如果一个 AMP 发生故障,则可以访问备用行。这样,即使一个 AMP 发生故障,数据仍然可以通过备用 AMP 获得。备用选项可以在创建表时或创建表后使用。备用可确保始终将表行的第二副本存储在另一个 AMP 中,以防止 AMP 故障导致数据丢失。但是,备用占据了插入/删除/更新操作的两倍存储空间和 I/O。
以下图表显示了如何将行的备用副本存储在另一个 AMP 中。
Down AMP Recovery Journal
当 AMP 发生故障并且表受到备用保护时,会激活 Down AMP 恢复日志。此日志会跟踪对发生故障的 AMP 的数据的所有更改。日志会在集群中剩余的 AMP 上激活。这是一个自动过程,并且无法禁用。当有故障的 AMP 恢复后,Down AMP 恢复日志中的数据将与 AMP 同步。完成此操作后,将丢弃日志。
Cliques
隔离是一种机制,Teradata 使用它来保护数据免遭节点故障的影响。隔离只不过是一组共享一组公共磁盘阵列的 Teradata 节点。当一个节点发生故障时,有故障节点的 vproc 将迁移到隔离中的其他节点,并继续访问其磁盘阵列。
Teradata - User Management
本章讨论了 Teradata 中用户管理的各种策略。
Users
使用 CREATE USER 命令创建用户。在 Teradata 中,用户类似于数据库。它们都可被分配空间并包含数据库对象,只不过用户被分配了密码。
Accounts
创建新用户时,可以将用户分配给一个帐号。CREATE USER 中的 ACCOUNT 选项用于分配帐号。用户可被分配给多个帐号。
Syntax
以下是使用帐户选项的 CREATE USER 的语法。
CREATE USER username
PERM = n BYTES
PASSWORD = password
ACCOUNT = accountid
Example
以下示例创建用户 TD02,并将帐户分配为 IT 和 Admin。
CREATE USER TD02
AS
PERMANENT = 1000000 BYTES
PASSWORD = abc$123
TEMPORARY = 1000000 BYTES
SPOOL = 1000000 BYTES
ACCOUNT = (‘IT’,’Admin’);
用户可以在登录 Teradata 系统时或使用 SET SESSION 命令登录系统后指定帐户 ID。
.LOGON username, passowrd,accountid
OR
SET SESSION ACCOUNT = accountid
Teradata - Performance Tuning
本章讨论 Teradata 中的性能调优过程。
Explain
性能调优的第一步是针对查询使用 EXPLAIN。EXPLAIN 计划提供优化器执行查询的详细信息。在 EXPLAIN 计划中,检查关键字(如置信级别、已使用的联接策略、假脱机文件大小、重新分配等)。
Teradata - FastLoad
FastLoad 实用工具用于将数据加载到空表中。因为它不使用瞬态日志,所以数据可以快速加载。即使目标表是 MULTISET 表,它也不会加载重复行。
How FastLoad Works
FastLoad 分两阶段执行。
Phase 1
-
解析引擎从输入文件读取记录,并将一个块发送到每个 AMP。
-
每个 AMP 存储记录块。
-
然后 AMP 对每个记录进行哈希处理,并将它们重新分配到正确的 AMP。
-
在第 1 阶段结束时,每个 AMP 都有自己的行,但它们不在行哈希序列中。
Example
使用以下记录创建一个文本文件,并将该文件命名为 employee.txt。
101,Mike,James,1980-01-05,2010-03-01,1
102,Robert,Williams,1983-03-05,2010-09-01,1
103,Peter,Paul,1983-04-01,2009-02-12,2
104,Alex,Stuart,1984-11-06,2014-01-01,2
105,Robert,James,1984-12-01,2015-03-09,3
下面是一个示例 FastLoad 脚本,用于将上述文件加载到 Employee_Stg 表中。
LOGON 192.168.1.102/dbc,dbc;
DATABASE tduser;
BEGIN LOADING tduser.Employee_Stg
ERRORFILES Employee_ET, Employee_UV
CHECKPOINT 10;
SET RECORD VARTEXT ",";
DEFINE in_EmployeeNo (VARCHAR(10)),
in_FirstName (VARCHAR(30)),
in_LastName (VARCHAR(30)),
in_BirthDate (VARCHAR(10)),
in_JoinedDate (VARCHAR(10)),
in_DepartmentNo (VARCHAR(02)),
FILE = employee.txt;
INSERT INTO Employee_Stg (
EmployeeNo,
FirstName,
LastName,
BirthDate,
JoinedDate,
DepartmentNo
)
VALUES (
:in_EmployeeNo,
:in_FirstName,
:in_LastName,
:in_BirthDate (FORMAT 'YYYY-MM-DD'),
:in_JoinedDate (FORMAT 'YYYY-MM-DD'),
:in_DepartmentNo
);
END LOADING;
LOGOFF;
Executing a FastLoad Script
在创建 input 文件 employee.txt 并且 FastLoad 脚本被命名为 EmployeeLoad.fl 后,您可以在 UNIX 和 Windows 中使用以下命令运行 FastLoad 脚本。
FastLoad < EmployeeLoad.fl;
执行上述命令后,FastLoad 脚本将运行并生成日志。在日志中,您可以看到 FastLoad 处理的记录数量和状态码。
**** 03:19:14 END LOADING COMPLETE
Total Records Read = 5
Total Error Table 1 = 0 ---- Table has been dropped
Total Error Table 2 = 0 ---- Table has been dropped
Total Inserts Applied = 5
Total Duplicate Rows = 0
Start: Fri Jan 8 03:19:13 2016
End : Fri Jan 8 03:19:14 2016
**** 03:19:14 Application Phase statistics:
Elapsed time: 00:00:01 (in hh:mm:ss)
0008 LOGOFF;
**** 03:19:15 Logging off all sessions
FastLoad Terms
以下是 FastLoad 脚本中常用的术语列表。
-
LOGON − 登录到 Teradata 并发起一个或多个会话。
-
DATABASE − 设置默认数据库。
-
BEGIN LOADING − 标识要加载的表。
-
ERRORFILES − 标识需要创建/更新的 2 个错误表。
-
CHECKPOINT − 定义何时进行检查点。
-
SET RECORD − 指定输入文件格式为格式化、二进制、文本或非格式化。
-
DEFINE − 定义输入文件布局。
-
FILE − 指定输入文件名和路径。
-
INSERT − 将输入文件中的记录插入到目标表中。
-
END LOADING − 初始化 FastLoad 的第 2 阶段。将记录分发到目标表中。
-
LOGOFF − 结束所有会话并终止 FastLoad。
Teradata - MultiLoad
MultiLoad 能够一次加载多张表,它还可以执行不同类型的任务,比如 INSERT、DELETE、UPDATE 和 UPSERT。它一次最多可以加载 5 张表,并且在一个脚本中最多可以执行 20 个 DML 操作。MultiLoad 不需要目标表。
MultiLoad 支持两种模式 −
-
IMPORT
-
DELETE
MultiLoad 除目标表外,还需要一个工作表、一个日志表和两个错误表。
-
Log Table − 用于维护加载期间进行的检查点,该检查点将用于重新启动。
-
Error Tables − 当错误发生时,这些表会在加载期间插入。第一个错误表存储转换错误,而第二个错误表存储重复记录。
-
Log Table − 维护 MultiLoad 每个阶段的结果,以便重新启动。
-
Work table − MultiLoad 脚本针对每个目标表创建一个工作表。工作表用于保存 DML 任务和输入数据。
Limitation
MultiLoad 有一些限制。
-
目标表上不支持唯一辅助索引。
-
Referential integrity not supported.
-
Triggers not supported.
How MultiLoad Works
MultiLoad 导入有五个阶段 −
-
Phase 1 − 预备阶段 – 执行基本的设置活动。
-
Phase 2 − DML 事务阶段 – 验证 DML 语句的语法,并将它们带入 Teradata 系统。
-
Phase 3 − 获取阶段 – 将输入数据带入工作表并锁定该表。
-
Phase 4 − 应用阶段 – 应用所有 DML 操作。
-
Phase 5 − 清理阶段 – 释放表锁。
MultiLoad 脚本中涉及的步骤 −
-
Step 1 − 设置日志表。
-
Step 2 − 登录到 Teradata。
-
Step 3 − 指定目标表、工作表和错误表。
-
Step 4 − 定义输入文件布局。
-
Step 5 − 定义 DML 查询。
-
Step 6 − 命名 IMPORT 文件。
-
Step 7 − 指定要使用的 LAYOUT。
-
Step 8 − 启动加载。
-
Step 9 − 完成加载并终止会话。
Example
使用以下记录创建一个文本文件,并将该文件命名为 employee.txt。
101,Mike,James,1980-01-05,2010-03-01,1
102,Robert,Williams,1983-03-05,2010-09-01,1
103,Peter,Paul,1983-04-01,2009-02-12,2
104,Alex,Stuart,1984-11-06,2014-01-01,2
105,Robert,James,1984-12-01,2015-03-09,3
以下示例为一个 MultiLoad 脚本,该脚本读取 employee 表中的记录并将记录加载到 Employee_Stg 表中。
.LOGTABLE tduser.Employee_log;
.LOGON 192.168.1.102/dbc,dbc;
.BEGIN MLOAD TABLES Employee_Stg;
.LAYOUT Employee;
.FIELD in_EmployeeNo * VARCHAR(10);
.FIELD in_FirstName * VARCHAR(30);
.FIELD in_LastName * VARCHAR(30);
.FIELD in_BirthDate * VARCHAR(10);
.FIELD in_JoinedDate * VARCHAR(10);
.FIELD in_DepartmentNo * VARCHAR(02);
.DML LABEL EmpLabel;
INSERT INTO Employee_Stg (
EmployeeNo,
FirstName,
LastName,
BirthDate,
JoinedDate,
DepartmentNo
)
VALUES (
:in_EmployeeNo,
:in_FirstName,
:in_Lastname,
:in_BirthDate,
:in_JoinedDate,
:in_DepartmentNo
);
.IMPORT INFILE employee.txt
FORMAT VARTEXT ','
LAYOUT Employee
APPLY EmpLabel;
.END MLOAD;
LOGOFF;
Teradata - FastExport
FastExport 实用程序用于将数据从 Teradata 表导出到平面文件中。它还可以生成报告格式的数据。可以使用 Join 从一个或多个表中提取数据。由于 FastExport 以 64K 块导出数据,因此它对于提取大量数据非常有用。
Example
考虑以下 Employee 表。
EmployeeNo |
FirstName |
LastName |
BirthDate |
101 |
Mike |
James |
1/5/1980 |
104 |
Alex |
Stuart |
11/6/1984 |
102 |
Robert |
Williams |
3/5/1983 |
105 |
Robert |
James |
12/1/1984 |
103 |
Peter |
Paul |
4/1/1983 |
以下是 FastExport 脚本的一个示例。它从 employee 表中导出数据,并写入到文件 employeedata.txt 中。
.LOGTABLE tduser.employee_log;
.LOGON 192.168.1.102/dbc,dbc;
DATABASE tduser;
.BEGIN EXPORT SESSIONS 2;
.EXPORT OUTFILE employeedata.txt
MODE RECORD FORMAT TEXT;
SELECT CAST(EmployeeNo AS CHAR(10)),
CAST(FirstName AS CHAR(15)),
CAST(LastName AS CHAR(15)),
CAST(BirthDate AS CHAR(10))
FROM
Employee;
.END EXPORT;
.LOGOFF;
Teradata - BTEQ
BTEQ 实用工具是 Teradata 中的一个强大实用工具,可以在批处理和交互模式下使用。它可用于运行任何 DDL 语句、DML 语句、创建宏和存储过程。BTEQ 可用于从平面文件导入数据到 Teradata 表,还可用于将数据从表中提取到文件或报告。
BTEQ Terms
以下是 BTEQ 脚本中常用的术语列表。
-
LOGON - 用于登录到 Teradata 系统。
-
ACTIVITYCOUNT - 返回上一个查询影响的行数。
-
ERRORCODE − 返回前一个查询的状态代码。
-
DATABASE − 设置默认数据库。
-
LABEL − 向一组 SQL 命令分配一个标签。
-
RUN FILE − 执行文件中包含的查询。
-
GOTO − 将控制权转移到标签。
-
LOGOFF − 从数据库注销并终止所有会话。
-
IMPORT − 指定输入文件路径。
-
EXPORT − 指定输出文件路径并启动导出。
Example
以下是一个 BTEQ 脚本示例。
.LOGON 192.168.1.102/dbc,dbc;
DATABASE tduser;
CREATE TABLE employee_bkup (
EmployeeNo INTEGER,
FirstName CHAR(30),
LastName CHAR(30),
DepartmentNo SMALLINT,
NetPay INTEGER
)
Unique Primary Index(EmployeeNo);
.IF ERRORCODE <> 0 THEN .EXIT ERRORCODE;
SELECT * FROM
Employee
Sample 1;
.IF ACTIVITYCOUNT <> 0 THEN .GOTO InsertEmployee;
DROP TABLE employee_bkup;
.IF ERRORCODE <> 0 THEN .EXIT ERRORCODE;
.LABEL InsertEmployee
INSERT INTO employee_bkup
SELECT a.EmployeeNo,
a.FirstName,
a.LastName,
a.DepartmentNo,
b.NetPay
FROM
Employee a INNER JOIN Salary b
ON (a.EmployeeNo = b.EmployeeNo);
.IF ERRORCODE <> 0 THEN .EXIT ERRORCODE;
.LOGOFF;
上面的脚本执行以下任务。
-
Logs into Teradata System.
-
Sets the Default Database.
-
创建名为 employee_bkup 的表。
-
从 Employee 表中选择一条记录,以检查表中是否有任何记录。
-
如果表为空,则删除 employee_bkup 表。
-
将控制权转移到标签 InsertEmployee,它将记录插入 employee_bkup 表
-
检查 ERRORCODE,确保在每个 SQL 语句之后该语句都成功执行。
-
ACTIVITYCOUNT 返回上一条 SQL 查询选择的/影响的记录数。