Bootstrap

11G Concept 第二章翻译 table and table cluster(表和table cluster,这个名词不翻译)

前面第一章是简单介绍了一下Oracle 数据库

而第二章到第六章则是正文内容,属于正文的第一块

Part I Oracle Relational dataStructures(Oracle关系数据结构)

本Part 描述了Oracle数据库的基础数据结构,包括 数据完整性规则,以及一些存着metadata的结构(metadata指元数据,具体意思自己百度吧)

第二章Tables and Table Clusters(表及TableClusters)

本章简单介绍了各种schemaObjects。以及详细讨论各种表。

表是schema objects中最常使用到的。

 

Introduction to SchemaObjects 介绍Schema中的各种对象

一个数据库schema 是个逻辑的容器,容器里放着一大堆data structures(数据结构),这些数据结构就叫做schemaobjects.

例如:表,索引

schemaobjects的创建和操作都是通过SQL来完成。

每个数据库用户都有密码,以及各种各样的数据库权限.每个用户都有属于自己的schema,且schema的名字和用户名一样。

例如:举个例子 hr用户有hr Schema,这个Schema包含着schemaobjects,比如一个叫employee的表。在生产数据库中,大多数情况下一个账户代表的是一个应用,而不是真的一个人。

在schema中,每个类型的的schemaobject对象都有自己唯一的名称。例如hr.employees指代在hr Schema中的employees表

下图描述了一个叫hr的schema以及它拥有者(也就是指hr用户)还有在schema中的schema objects


Schema Object Types (SchemaObject的各种类型)

在关系型数据库中,最重要的schemaobject就是表。

表用行的形式存储数据

OracleSQL 还可以创建和操作其他类型的schema object,包括:

·Indexes(各种索引)

  索引是个schema object。它帮助用户能够直接的,快速的去访问相关行。Oracle database 支持几种index 类型。还有一种叫表叫索引组织表,这种表的记录都是按照索引的结构存储的(也就是已经排好序的)。

·Partitions(各种分区)

  分区就是大表或者大索引的一部分.每个分区有它自己的名字还可以有它自己的存储特性

·Views(视图)

  视图是定制的数据显示,从一个或者多表,或者其他视图中。你这可以把它理解为复杂的查询语句不过这些语句是存储起来的。视图并不真正的拥有数据。

·Sequences(序列)

  序列是一个用户创建,多个用户都能共享使用的。它用来形成整数,基本上,序列都被用在生成主键列值.

·Dimensions(维)

  一个维定义了一个 parent-chidrelationship beween  paris of column sets(两组列)(感觉怎么翻都很拖沓,干脆不翻这句)

  维通常用在可分类的数据 比如 客户信息,产品信息, 以及时间

·Synonyms(同义词)

  同义词就是其他人对象的别名。由于同义词只是一个别名,它只需要在数据字典中定义一下就可以,不需要存储空间

·PL/SQL subprogramsand packages(过程和包)

  PL/SQL是OracleSQL的程序化扩展,PL/SQLsubprogram 指的就是一个PL/SQL块,可以被调用。PL/SQL package 就是将一个subprogram 和它用到的变量啊,cursor啊放到一起,方便别人调用。

 

还有一些其他类型的对象,它们也是通过SQL创建和操作的,但是它们不属于schema,所以它们不是schema objects ,它们包括:users(用户),roles(角色),contexts,以及directory objects(目录对象,用在expdp/impdp)

 

Schema object Storage(Schemaobject的存储方式)

一部分schema objects存储数据到 名叫segments(段)的逻辑存储结构。例如,一个没有分区的普通表(也叫堆表)/索引都有属于自己的segment。一一对应。

而其他的比如view或者sequence,都仅仅只有元数据(存放在数据字典),

这一节只介绍拥有segment的schemaobjects

 

Oracle 数据库将schemaobject逻辑的存在tablespace(表空间), 而schema和tablespaces是没有任何关系的,不要放在一起理解。表空间可以存放不同schema的schema objects,而且每个schema的schema objects可以放在不同的表空间。一个表空间由多个数据文件物理组成,而一个segment中的数据,可以物理的存放在多个数据文件上。

 

下图显示了segment,tablespace 和数据文件的关系。一个segment横跨属于一个表空间的两个数据文件。一个segment不能横跨多个表空间。


Schema ObjectDependencies(Schema Object之间的依赖关系)

一些schema objects 会引用别的schemaobjects,例如:一个视图其实就是一个查询,这个查询依赖于一些表或者视图。又例如:一个PL/SQL subprogram 引用了其他的subprogram

如果,对象A的定义中引用了对象B,则A是dependentobject(相对于B来说),而B是一个referenced object(相对于A来说).

Oracle数据库提供了一个自动机制来确保dependent object引用的数据永远是ferenced objects中当前的。当referenced object结构发生改变时,则可能会影响它的dependent object,dependent object可能会被标记为失效.

例如:如果一个用户删了一个表,基于这个表的视图,全部都会失效。

 

失效的dependent object 想重新生效,必须将依赖关系修复后重新编译。

运行失效的存储过程,重新编译操作会自动进行。

下面的例子是说明schemaobjects怎样创建dependencies,这个脚本创建了test_table表,以及一个存储过程来查询这个表:

CREATETABLE test_table(col1 INTEGER, col2 INTEGER);

CREATEOR REPLACE PROCEDURE test_proc

AS

BEGIN

  FOR x IN (select col1,col2 FROM test_table)

  LOOP

--processdata

  END LOOP;

END;

/

查一下test_proc的状态:

SQL>SELECTOBJECT_NAME,STATUS FROM USER_OBJECTS WHERE OBJECT_NAME='TEST_PROC';

 

OBJECT_NAME  STATUS

-------------------  ----------

TEST_PROC     VALID

 

test_table表增加一列col3,这时候存储过程依然是valid,因为它和col3没有任何依赖关系

SQL>ALTER TABLE test_table ADD col3 NUMBER;

 

Tablealtered.

 

SQL>SELECTOBJECT_NAME,STATUS FROM USER_OBJECTS WHERE OBJECT_NAME='TEST_PROC';

 

OBJECT_NAME  STATUS

-------------------  ----------

TEST_PROC     VALID

 

可是,修改了col1列的数据类型,而test_proc存储过程是依赖于这列的,这将使得test_proc存储过程失效:

SQL>ALTERTABLE test_table MODIFY col1 VARCHAR2(20);

 

Tablealtered.

SQL>SELECTOBJECT_NAME,STATUS FROM USER_OBJECTS WHERE OBJECT_NAME='TEST_PROC';

 

OBJECT_NAME           STATUS

-------------------  ----------

TEST_PROC              NVALID

 

运行或者重新编译一下这个存储过程,使它恢复valid,必须像下面显示的:

SQLEXECUTE test_proc

 

PL/SQLprocedure successfully completed.

SQL>SELECTOBJECT_NAME,STATUS FROM USER_OBJECTS WHERE OBJECT_NAME='TEST_PROC';

 

OBJECT_NAME        STATUS

------------------  ----------

TEST_PROC            VALID

 

SYS and SYSTEM Schemas

所有的Oracle数据库都有一些默认的管理帐号,这些账号原则上只供DBA使用。DBA这些帐号来执行一些像开关数据库,管理存储和内存,创建数据库,创建用户等等的管理任务。

管理账户SYS,这个用户在创建数据库的时候会自动创建.这个账户拥有最高的权限。

而与它关联的SYS schema则存折数据字典的基表和视图.这些基表和视图对于Oracle数据库来说非常重要.

存在SYS中的这些基表和视图,只能由数据库自己操作,用户绝对不可以擅自操作.

 

SYSTEM账户同样在数据库创建的时候自动创建.而SYSTEM schema里面存了一些另外的表和视图,这些东西同样也是用来显示一些管理信息,还有一些内部表和视图也存在进去,Oracle数据库一些可选的组建可能会用到。

永远不要用SYSTEM schema来存一些与管理员无关的表(比如说业务表).

 

Sample Schemas(例子 schema)

Oracledatabase还可能有例子schema,这个实例schema能让你根据oracle上的实例来实验一些普通的数据库任务.

hrschema 就是一个例子schema,它包括了 employees,departments,locations histories等等表,以及相应的一些信息。

下图就是hr schema中的完整关系图,Concepts中的大多数实验都根据这个schema编写的。


 

Overview of Tables(表的概述)

一个表描述的就是一个entity的一些非常明显的特征信息。举个例子:

一个雇员就可以是一个entity。

Oracle数据库的表分成以下几种

·Relational tables(关系表)

  关系表有一些列,是最常见的表

·Object tables

  这种表可以说是一种模版,普通表(relationaltables)创建的时候可以直接根据已经创建好的Object tables来创建。例如:create table 普通表 of  (Object table); 不用指定列什么的了。

 

一个的Relational table(关系表),可以根据结构分成以下几种:

·Heap-organizedtable(堆表),存储的行没有顺序,堆,就是把行随便堆在那就完事。

  CREATE TABLE命令默认创建的就是这种表。

·Index-organizedtable(索引组织表,IOT)这种表将行按照主键的顺序进行排列。

  对于一些应用,IOT能增强性能以及更有效的利用磁盘空间。

·External table(外部表),这种表是一种只读表,这种表只有metadata存在数据库中,但是真正的数据并不存在数据库中。(也就是数据库中只存表的结构,数据实际在外面)

 

表分两种,普通表和临时表。普通表的定义和数据会一直保存,除非你删除它。而临时表则不同,它数据是临时的,有两种级别事务级,session(会话级))

临时表用在一些只需要临时生成的数据,临时使用,不用保存。

本小节分为以下几个主题:

·Columns and Rows(列,行)

·Example:CREATE TABLEand ALTER TABLE statements(举例create table alter table)

·Oracle Data Types(列的数据类型)

·IntergrityConstraints(完整性约束)

·Object Tables (Object Table就是上面说的模版表)

·Temporary Tables( 临时表)

·External Tables(外部表)

·Table Storage(表的存储方式,也就是强调一下segment)

·Table Compression(表压缩)

 

Columns and Rows

定义一个表,需要指定一个表名,以及一大堆列。一个列都表示一个属性(特征),例如:

employees表中employee_id列就是指 雇员(employee)的ID属性。

一般,当你建表的时候,你需要给每个列 一个列名,一个数据类型,一个宽度。例如:

employee_id列的数据类型就是NUMBER(6),6就是宽度。说明这列只能插入数字,且最多6位。有些类型的宽度是预先设定好的,比如DATE。

表可以有virtual column(虚列),virtualcolumn不需要耗费磁盘空间。数据库在用户需要用到的时候会将虚列派生出来,例如:比如income虚列可以对salary ,commission_pct列起作用

表创建完成后,可以使用SQL插入,查询,删除和更新rows(行)。row(行)就是一条记录,这条记录由一堆相关列的值组成.例如:

employees中的一行,用来描述一个指定empoyee的详细信息

 

Example:CREATE TABLE andALTER  TABLE statements

(createtable 和alter table的例子)

 

OracleSQL中创建表的命令是 CREATE TABLE.

CREATE TABLE employees

    (employee_id    NUMBER(6)

    ,first_name     VARCHAR2(20)

    ,last_name      VARCHAR2(25)

        CONSTRAINT    emp_last_name_nn  NOT NULL

    , email          VARCHAR2(25)

       CONSTRAINT     emp_email_nn  NOT NULL

    ,phone_number   VARCHAR2(20)

    ,hire_date      DATE

       CONSTRAINT    emp_hire_date_nn  NOT NULL

    , job_id         VARCHAR2(10)

       CONSTRAINT     emp_job_nn  NOT NULL

    , salary         NUMBER(8,2)

    ,commission_pct NUMBER(2,2)

    ,manager_id     NUMBER(6)

    ,department_id  NUMBER(4)

    ,CONSTRAINT     emp_salary_min

                    CHECK (salary > 0)

    ,CONSTRAINT     emp_email_uk

                    UNIQUE (email)

    ) ;

这个例子显示了hr 例子schema中 employees表的创建语句。

这条语句指定一些列,如employee_id,­first_name等,为每列指定了数据类型如NUMBER,DATE等

 

下面来一个修改表结构的列子,通过ALTERTABLE

ALTER TABLE employees

ADD ( CONSTRAINT    emp_emp_id_pk

                      PRIMARY KEY (employee_id)

    ,CONSTRAINT     emp_dept_fk

                      FOREIGN KEY (department_id)

                        REFERENCES departments

    ,CONSTRAINT     emp_job_fk

                      FOREIGN KEY (job_id)

                        REFERENCES jobs (job_id)

    ,CONSTRAINT     emp_manager_fk

                      FOREIGN KEY (manager_id)

                        REFERENCES employees

    ) ;

上面例子用ALTER TABLE语句给employees表增加了一个完整性约束,完整性约束强制保证了生意规则,预防了无效的信息进入到表。

 

下面再显示个SELECT 返回的结果,

EMPLOYEE_IDFIRST_NAME  LAST_NAME   SALARY  COMMISSION_PCT  DEPARTMENT_ID

----------- -----------     -------------        -------       --------------       -------------

        100 Steven      King            24000                           90

        101 Neena       Kochhar         17000                           90

        102 Lex         De Haan         17000                           90

        103 Alexander   Hunold           9000                           60

        107 Diana       Lorentz          4200                           60

        149 Eleni       Zlotkey         10500             .2            80

        174 Ellen       Abel            11000             .3            80

        178 Kimberely   Grant            7000            .15

上面的这个例子显示了表,列,行的一些重要特种:

·行描述了一个雇员的属性:name(名字),salary(工资),department(所属部门)等。例如,第一行显示了一个雇员,名叫Steven King的信息。

·列描述了雇员的属性,在这个例子中,employee_id列是主键,主键的意思是列中每个值必须都是唯一的,要保证任何两个雇员的雇员ID都必须是不同的。

·非关键列则可以包含相同的值,比如这里,ID为101和102的salary列,值都是17000.

·foreign key(外键)列引用一个本表或者其他表的主键列,或者唯一性值列。在这个例子中,department_id就引用了departments表的department_id列。

·filed(字段),是行和列的交叉点,它只能有一个值,例如104雇员的department_id。这就是一个字段,在这里,它的值是60。

·列可以没有值,在Oracle里,没有值 称为NULL值。雇员100的commission_pct列的值就是NULL,而雇员149相同列值为.2。

  一个列允许有NULL值,除非是主键,或者这列有NOTNULL完整性约束。

 

Oracle Data Types(Oracle 数据类型 )

每列都有数据类型,数据类型就是 特定的存储格式,约束,以及可插入值的允许范围。

存储格式其实就是一组 对于值的固定的属性集,这些属性使Oracle数据库处理一种数据类型的方法,和处理另外一种是不相同的。

例如:你可以对NUMBER数据类型做乘法,但是对RAW属类型却不行。

当你创建一个表,你必须指定每列的数据类型,之后插入列的每个值都会被认为是相应的数据类型。

Oracle数据库提供一些数据类型。最常用到的数据类型都属于下面这些分类:

·Character Data Types(字符型)

·Numeric Data Types(数字型)

·Datatime Data Types(日期时间型)

·Rowid Data Types(Rowid型,行的物理存放位置)

·Format Model andData Types(将数值或者时间当成字符型存起来,需要按照一定的格式)

还有其他一些重要的数据类型包括 raw,largeobjects(LOBs),collections。

PL/SQL的常量和变量也都有数据类型。包括BOOLEAN(布尔),reference types(引用),composite types(records,也就是行),以及一些用户自定义的类型。

 

Character Data Types(字符型)

字符型储存 字符型数据,字符型的数字也算字符型。最常用的字符型是VARCHAR2,它是储存字符最高效的选择。

其中的值 与字符集有关(比如从别的库搞出来的数据,在这里搞进去,但是两个库字符集不匹配,那就变乱码了)

数据库字符集是在数据库创建的时候就建立好的!举几个字符集的例子:Unicode UTF-8,7-bit ASCII,EBCDIC。

 

VARCHAR2 and CHAR Data Types

VARCHAR2数据类型存储可变长的字符文本(literals),专业属于literal(文本)和constant value(常量)是同义词都是指固定不变的数据值。

例如'LILA','St.GeorgeIsland' ,以及'101' 这些全部都是字符文本,而5001是数字文本.

字符文本被涵盖在两个单引号里,这样数据库才能知道它们没有特殊意义。

 

当你你创建的表中有VARCHAR2列,你指定了最大的字符长度。比如Name列 VARCHAR(25),它的意思是任务存储进这个列的名字可以最大不超过25个字节。

对于每行来说,Oracle存储的每个在name列的值都是可变长的。除非数据已经到了最大长度。

举个例子,在一个单字节的字符集中,如果输入了10个字符进name列,则行保存进数据块中时值保存10个字符(10 byts) 而不是25。使用VARCHAR2会减少磁盘的消耗。

 

对比起VARCHAR2,CHAR存储的是 不可变长的字符串。比如输入了25,你只插入了10,但是还是会按照25保存。其他15用空格填充

 

NCHAR and NVARCHAR2 Data Types

NCHAR 和NVARCHAR2数据类型存的是Unicode字符数据。Unicode是universal encode(通用编码)字符集,用这个字符集可以存储任何语言。

NCHAR 特性和CHAR对应,只不过使用的是national(国家)字符集,而NVARCHAR2与VARCHAR2对应。

当你创建数据库的时候,你也会指定一个nationalcharacter set。国家字符集。这个字符集就是为 NCHAR ,NVARCHAR2准备的,这字符集要么是AL16UTF16,要么是UTF8。这两个字符集都是使用了Unicode encoding

NCHARNVARCHAR设置长度的时候,只能设置单位是char的。不能设置单位是bytes的

 

Numeric Data Types(数值类型)

oracle数据库的数值类型是按照可变长模式存储的。

每个值都是按照科学计数法存储的,会有一个字节用来存储指数。

数据库最多用20个bytes来存储尾数(小数点后面的),尾数是floating-point(浮点数)的一部分,包含了它显著的位数。

Oracle数据库不储存开头的0 和结尾的0

 

NUMBER DATA type(数字型)

数字型存储了固定和浮点类型的数字。数据库可以存储几乎任何大小的数字.在不同的操作系统上运行的Oracle数据库,数值型的格式是一致的.

如果你必须要存储数值类型,则NUMBER是最常用,也是最推荐的。

 

NUMBER的格式是NUMBER(p,s),p和s分别指得下列意思:

·Precision(p)(精度)

  precision指的是总共多少位,如果p没有指定,则这个字段存储的值和应用提供的完全一样,没有任何四舍五入

·Scale(s)(刻度,其实就是指小数位数)

  如果s指定,则等于0.例如

  number(8,2)则总共有8位,其中2位是小数。

Floating-Point Numbers(浮点数)

Oracle数据库提供了两种浮点 数据类型:BINARY_FLOAT和BINARY_DOUBLE。

这两种类型能支持NUMBER类型所支持的所有功能。不过,NUMBER使用的是10进制精度,而BINARY_FLOAT和BINARY_DOUBLE使用的是2进制精度,这种精度使得计算更快,并且通常能减少存储需求。

BINARY_FLOAT和BINARY_DOUBLE是大概的数值类型,它们存储了近似的十进制。而不是精确的表示,举个例子:值0.1是没办法通过BINARY_DOUBLE和BINARY_FLOAT精确表示的。

它们经常被用到科学运算。它们的行为和JAVA中的FLOAT和DOUBLE很相似。

 

Datetime Data Types(时间数据类型)

数据时间的类型有DATE和TIMESTAMP.

Oracle数据库提供对 时区(time zone)的全面支持

 

DATE data Type(日期型)

DATE类型里面存了日期 和时间,日期时间 可以用字符或者数字类型来表示,而DATE则是对其进行了特殊的关联。推荐使用date类型来存放日期时间。

 

在数据库内部,date存放的格式是数字,date会存成定长的7个字节。分别代表 世纪,年,月,日,小时,分钟,秒。

DATE类型全面支持算术运算。比如+1就是增加一天加0.5就增加半天。

数据库显示时间是根据指定的 formatmodel (格式模版). format model是日期时间按照字符型的样子来进行表示(但它实际是按照数字存放的)

标准默认的时间格式的DD-MON-RR,显示出来为02-JAN-09

RR 和YY很想,都是将年的最后两位显示出来,但是它们返回的后两位,代表的年份可能不是一个世纪的。比如说,在1909年的话,数据库显示 01-JAN-09,,如果日期格式用RR,则09代表2009,而如果格式使用YY,则代表1909,你可以改变默认的日期显示格式在INSTANCE级别和SESSION级别。

Oracle 数据库存储时间 格式是HH:MI:SS,如果没有插入时间部分,则默认显示是00:00:00 A.M .如果日期部分没有插入,则默认是当前月的第一天。

 

TIMESTAMP Data Type(时间戳数据类型)

TIMESTAMP数据类型是DATE类型的扩展,除了DATE能够存储的信息,它还另外加了秒以下的单位。TIMESTAMP类型对于存储精确的时间是非常有效的,比如应用必须能够跟踪事件一个时间的顺序(比如一秒可能出现了很多事件)

TIMESTAMPWITH TIME ZONE和TIMESTAMP WITH LOCAL TIME ZONE是TIMESTAMP其中的两个类型,都是能够感应时区的(也就是和时区可以关联起来).当用户查询出这两种类型的值,则值会根据用户的时区自动进行调整。

这两种类型对于跨时区的系统是很有用的

 

Rowid Data Types(Rowid 数据类型)

存在数据库中的每行,都有自己的一个唯一地址.Oracle数据库使用ROWID数据类型来存储这个地址(rowid).

Rowid有以下几种类型:

·Physical rowids(物理rowid) 这类是被普通表,tablecluster,以及分区所使用。

·Logical rowids(逻辑 rowid) 这类是被index-organizedtables,IOT使用的。

·Foreign rowids(外部 rowid) 这类用来表示外部的表,比如通过网关访问的DB2的表,它们不是标准的Oracle 数据库 rowid。

 

Use of Rowids(Rowid的使用)

Oracle数据库,索引就是基于ROWID的。B-tree索引, 这个是索引最常用的类型,索引是将键值按照顺序排列,并且分开 放入到一些范围里(可用邮编来理解)

每个键值都与一个rowid关联,它指向了相关的行地址,使应用可以通过索引快速访问。

终端用户和应用开发同样可以在一些重要的功能上 使用rowid

·Rowid是访问指定行最快的方式

·Rowid 在一个给定的表中,是绝对的唯一标识

你可以创建一个表,列用ROWID数据类型 。例如:你可以定义一个有rowid类型列的 意外表,用来存一些违犯了完整性约束 行的rowid。

列用rowid类型,表现和其他表的列是一样的:列可以被更新等。

 

ROWID Pseudocolumn (ROWID 虚列)

Oracle数据库中的每个表都有 虚列,名叫ROWID. 一个序列的表现像是表的列,但是它并不真实储存在表中。你可以select 序列,但是你不能insert update 或者delete它们的值。一个虚列类似一个没有参数的功能函数。一个没有参数的函数通常会返回一个相同的值,但是虚列通常对于每行都会返回一个不同的值。

下面是一个例子:查询empolyee_id等于100的rowid

SQL>SELECTROWID FROM employees WHERE employee_id=100;

ROWID

---------------------------

AAAPecAAFAAAABSAAA

 

Format Models and Data Types (格式化模型和数据类型)

formatmodel是字符文字描述存储在一个字符类型中的datetime或数值类型。

formatmodel并不真正改变值在数据库中的表现。

 

当你将一个字符值转换成日期或者数字的时候,formatmodel决定了数据库该怎样翻译。

SQL中你可以使用formatmodel作为TO_CHAR和TO_DATE函数的参数。用来格式化从数据库中读出的值,或者将值格式化后存入数据库。

 

下面的语句查询了 部门80的雇员们的工资,并且将查出来的工资使用to_char格式化成字符串形式,format model为 '$99,990.99'

SQL>SELECT last_name employee,TO_CHAR(salary,'$99,990.99')

     FROM employees

     WHERE department_id=80 ANDlast_name='Russell';

EMPLOYEE   TO_CHAR(SAL

-----------------------------------

Russell       $14,000.00

 

而下面的例子则是 更新 hire_date 。通过使用TO_DATE,将字符串'1998 0520'格式化成了时间格式

SQL>UPDATE employees

     SET hire_date = TO_DATE('1998 05 20','YYYYMM DD')

     WHERE last_name = 'Hunold';

 

Integrity Constraints(完整性约束)

表中一列或多列中对于插入值的限制规则,就是完整性约束.这些规则防止不合法的数据条目插入到表.同事完整性约束也可以防止表中数据删除,当一些依赖性存在时(外键)

 

当约束enabled时,则数据库会检查数据.如果数据不符合要求,是不会让它进入的.

当约束disabled时,数据不符合要求,但是也是可以进入的

 

在之前的例子例子中  CREATE  TABLE 语句指定了 NOT NULL 约束在一些列,比如last_name,email,hire_date等。

createtable中的constranit子句标明了段名,以及约束条件.

这个NOT NULL约束保证了指定列中不能有null值,也就是不能为空。

 

约束除了在创建表的时候可以弄,也可以在表创建完以后建立

约束也可以根据需要临时disabled(禁用)掉。

 

Object Tables(根据object type创建的表,就叫objecttable)

Oracleobject type。

object type定义一个逻辑架构,但是却不创建segment(段)

举例说明

CREATETYPE department_type AS OBJECT

   (d_name VARCHAR2(100),

   d_address VARCHAR2(200));

/

当department_type这个objecttable创建好后,可以根据它来创建object table

例如:

CREATETABLE department_obj OF department_type;

这样一个object table就创建好了,不需要指定列。列和之前object table的完全一样。

这时候可以直接插入数据了。

insertinto department_obj

     values('hr','10 Main st, Some town, CA');

和普通表一样,不过object table的每行都有一个逻辑的object identifier(OID),它在一个object table是唯一的。object table的OID列是隐藏列。

 

Temporary Tables(临时表)

临时表中数据 保存的周期 只有 transaction(事务)周期和session(会话)周期两种

临时表是不共享的。也就是说,每个session看到的一个相同的临时表,但是数据却是完全不同的(临时表中数据是私有的)

临时表对于应用中比如某些结果集要临时存一下。这时候是非常有效的。

举个例子:

选课软件使的大学生可以创建自己本学期的可选课程计划。每个计划 都可以用临时表中的一行来表示,在整个session(会话)期间,这个计划的数据都是私有的。当学生确定了一个上课计划,在应用会把这行 移到一张 永久表(非临时就叫永久).在这个session关闭时,这些在临时表中的计划数据,将会自动的删除掉。

 

Temporary Table Creation

CREATEGLOBAL TEMPORARY TABLE语句创建临时表。ON COMMIT 子句指定表的数据是事务级别(默认)还是session级别。

和其他数据库并不一样,当你在Oracle数据库创建临时表时,你创建了一个静态的定义。临时表是一个永久的对象描述,但是为空(不分配segment)  直到你的session插入数据到这个表。你创建临时表是提供给数据库本身,但并不提供给每个PL/SQL 存储过程。

 

英文临时表是静态的定义,你可以用CREATEINDEX去对它创建索引。创建在临时表上的索引也是临时的。你也可以创建视图和 触发器 在临时表上。

 

SegmentAllocation in Temporary Tables(临时表关于段的分配)

和永久表一样,临时表在数据字典中是有定义的。但是临时段却是在数据第一次插入到临时表的时候才分配,在没有插入数据前,临时表是不分配段的。当session或者事务结束时(两个级别)则临时段会 取消分配。也就是 临时段用完就又收回了。

 

External Tables(外部表)

外部表的实际数据都在外面。你可以使用SQL,PL/SQL,以及JAVA来查询外部数据

外部数据对于查询 平台文件非常有效,举个例子吧:一个基于sql的应用可能会从 txt文件中访问需要的记录,这些记录类似如下:

100,Steven,King

101,Neena,Kochhar

102,Lex,DeHaan

你可以创建一个外部表,将文件拷贝到外部表定义好的位置,然后使用sql 从txt文件中查询条目。

外部表对于ETL(extraction,transformation,loading)任务,这种任务普遍在数据仓库环境中。举个例子:外部表使得 数据库加载过程和转换过程 合并了。将需要的数据才载入到库,以便于数据库进一步处理。

 

External Table Creation(外部表的创建)

对数据库内部而言,创建一个外部表 其实就是在数据字段中添加一些元数据。和普通表不一样,一个外部表,并不存储数据,也不存储数据描述是怎样存储在外部的。外部表的元数据表了

CREATETABLE ... ORGANIZATION EXTERNAL 有两个部分,

第一个部分,external tabledefinition 描述了段的类型,这个definition(定义)像一个视图,它使SQL可以查询外部数据的时候,不将其再入到库。

第二个部分表示了外部数据是怎样和每个列挂钩的。

外部表是 只读表。除非创建表用CREATETABLE AS SELECT 以及使用ORACLE_DATAPUMP访问驱动器。

外部表的限制有1、不支持索引列,2、不支持虚拟列,3、不支持列对象。

 

External Table Access Drivers(外部表访问驱动器)

accessdriver 是一个API(应用程序接口),它解释了 database 的外部数据。这个访问驱动器运行在数据库内部,它被用来读外部表中的数据。这个访问驱动器以及外部表层是相关联的,用来执行将查询转换匹配到外部表中的数据。

下图解释了外部数据是怎样被访问到的。


Oracle提供两种访问驱动.ORACLE_LOADER(默认)和ORACLE_DATAPUMP.

ORACLE_LOADER通过SQL*Loader来只读的访问外部表.你用ORACLE_LOADER驱动时不能更新,或者创建,或者追加内容到外部表。

ORACLE_DATAPUMP驱动使你可以unload(卸下)外部数据,

这个操作包括从数据库中读取数据,并且插入数据到一个外部表,创建一个或多个外部文件。

 在外部文件创建后,则数据库不能在更新或者追加数据进去。

这个驱动器同样可以使你load(加载)外部数据,包括从外部表中读取,并且加载到数据库中。

 

Table Storage(表的存储)

Oracle 数据库使用 datasegment(段)用来保存表的数据。也被叫做 User Segment.一个segment包含由data blocks(数据块们)组成的extents(区)

 

表对应的段,默认是在用户自己的默认表空间中,如果create table的时候指定了则,则存储指定表空间(你要有权限往里写)

 

Table Organization(表的组织结构)

默认情况下,表的组织结构是 heap(堆),它的意思是数据库存放行的时候,怎么存快就怎么存,而不是按照一个用户特别指定的顺序。(堆表就是随便堆在那)。因此,heap(堆)组织表是中的行是无序存放的. 用户添加行,数据库则将行存放在段中的第一个可用位置.

当行被查询时,并不保证是它当时插入的顺序.

hr.departments表就是一个堆表,它的列表述的内容有 department ID,name,manager ID,以及location ID。当行插入的时候,数据库存放他们时,哪里有空就存在哪。

一个在表segment的数据库。可能存放着一堆无序的行,如下面这个样子


在一个表中,所有行的 列的顺序都是一样的,数据库通常存放列的方向是这个表创建时候指定的方向。但是,这里说的是通常,但并不是绝对。举个例子:如果一个表有一个列的类型是LONG,则Oracle数据库永远把这列的值存在最后。同样如果你添加一个新列进一个表,则这个新列成为最后一个列。

表可以包含virtual column(虚列),它不像普通的列,它并不消耗磁盘空间。当用户根据指定的表达式或者函数要计算一个返回集,并且里面有用到虚列,则数据库会将虚列派生出来(也就是当时才开始产生,返回完又没了)

你可以对它进行索引(注意 虚列和pseudocolumn是有区别的),收集它们的统计信息,以及创建完整性约束,因此,virtual 列其实和普通列非常相似

 

Row Storage(行的存储)

数据库存储行到数据块中,每个rowpiece只能存最多255列。

Oracle 数据库会尽可能的把每行数据存为一个row piece(行片),然后,如果一行的数据一个块放不下,或者如果一个行发生了更新,导致原本的块放不下了,则数据库这时将使用多个row pieces(行片)

tablecluster中的行和普通表中的一样,此外,table cluster中的行包含的信息中引用了它们使用的cluster key

 

Rowids of Row Pieces(行片的rowid)

rowid是一个占用了每行10个byte的物理地址。像"RowidData Types"中解释的一样,在堆表(普通表)中的每行都有唯一的rowid,它和row piece的物理地址一一对应。

在table cluster中,在不同表的行,它们在相同的数据块。它们可以有一样的rowid

 

Oracle 数据库内部使用rowid来构造索引。举个例子:在B-tree索引中的每个key都和一个rowid关,它指向了相关行的地址,使索引可以快速访问数据。

物理rowid是最快访问到行的方式。使数据库检索行在一个I/O就可以搞定。

 

Storage of Null Values(关于NULL值的存储)

null就是段中没有值。null表示 丢失,未知 或者不可用数据。

null是会被存储的,如果它在一堆有值的列的中间。在这种情况下,它们需要用1byte来存储段的长度(0)

如果行中最后追着一堆NULL,则这些null并不存储。举个例子,如果一个表中最后三列是null。在这些columns是不需要存储的。

 

Basic and OLTP Table Compression

基于字典的表压缩 ,这种压缩给普通表提供了很好的压缩比例.Oracle数据库支持以下几种基于字典的表压缩。

·Basic tablecompression(基本表压缩)

  这种压缩类型为 大块的加载操作 准备。数据库不能压缩使用传统DML修改的数据,你必须使用directpath load(直接路径载入),ALTER TABLE ...MOVE操作,或者online table redefinition(在线表重定义)用来实现 基础表压缩。

 

·OLTP tablecompression(OLTP表压缩)

  这种压缩方式专门为了OLTP准备,可以在数据还被SQL操作的时候进行压缩。

对于基本和OLTP 方式的表压缩,数据库存储压缩后的行 格式是 row-major。一个行的所有段都存储在一起,后面跟随的是下一行的所有段,依此类推

而相同的值将被替换为一个标记表中的一个指针,这个表存在块的头部。因此,将块解压缩而需要的相关信息已经在块自身存储了。

压缩后的数据块看起来和正常数据块很像。绝大多数能够用在标准数据块上的数据库特性和应用,也同样可以用在压缩后的数据块。

 

你可以在表空间,表,分区,子分区级别上申明压缩。

如果指定在表空间级别,则所有在这个表空间创建的表 默认就是压缩的。

可以使用下列命令引用 OLTP压缩到orders表:

ALTERTABLE orders COMPRESS FOR OLTP;

下面这个例子是CREATE TABLE 中对于一个分区指定了OLTP压缩,而其他分区则是基础压缩:

CREATETABLE sales(

       prod_id NUMBER NOT NULL,

       cust_id NUMBER NOT NULL, ...)

 PCTFREE 5 NOLOGGING NOCOMPRESS

 PARTITION BY RANGE (time_id)

  (partition sales_2008 values lessthan(to_date(...)) COMPRESS BASIC,

   partition sales_2009 values lessthan(MAXVALUE) COMPRESS FOR OLTP);

 

Hybird Columnar Compression(混合列压缩)

在混合列压缩中,数据库将一组行的相同列值存在一起.

数据块不将数据存储为row-major格式,使用了一个行和列组合起来的一种方法.       

把段的数据存在一起,根据相同的数据类型和相似的特点,通过极大的增强存储的使用来实现压缩的目的。压缩后的数据可以被任何SQL操作。虽然压缩级别其实比直接路径加载更高。数据库操作对于压缩对象是透明的,所以无需修改应用程序。

 

Types of Hybrid Columnar Compression(混合列压缩的类型)

如果你底层的存储支持混合列压缩,则你可以指定下列压缩类型,根据你的需要:

·WareHouseCompression(仓库压缩)

  这种压缩类型是对于存储空间的优化,它为了数据仓库类型准备

·Online archivalcompression(在线归档压缩)

  这种压缩方式是最高的压缩级别,它专门为了历史数据,不会发生变化的数据准备。

为了完成Warehouse oronline archival 压缩。你必须使用直接路径加载。ALTER TABLE ...MOVE操作,或者表在线重定义。

混合列压缩是用来优化数据仓库和Exadata存储的决策支持系统。在Exadata中查询使用了混合列压缩的表,性能最好,Exadata存储服务器是利用强大的处理能力,内存,以及Infiniband网络组成的。

  其他oracle存储系统也支持混合列压缩,而且提供和Exadata相同的空间使用,但是它不提供相同的查询性能。在这些存储系统中,混合列压缩用不经常访问的,老的归档数据是合理的。

 

CompressionUnits(压缩单元)

混合列压缩使用了一种逻辑结构叫compressionunit(压缩单元),它用来存储一组行。当你将数据加载到表中时,则数据库将一组行存储成列模式,每列的值都存储和压缩在一起。

在数据库把一堆行的列数据都压缩后,数据库以后将从compression unit中获取数据。

举个例子:

你对daily_sales表执行了混合列压缩.在每天结束时,你得把销售的物品和数量填充进来.

有物品ID和date 形成组合主键,下表显示daily_sales中的一个子集


假设上表的行都存在一个压缩单元中。混合列压缩将把每个段的值存储在一起,而且使用多重算法去压缩每列。数据库选择算法是基于多种因素影响,包括段的数据类型,段中值的基数以及用户选择的压缩级别。

 

像下图显示,每个压缩单元可以跨过多个块。而特定列的值可能跨过,也可能没跨过多块。


混合列压缩会产生row锁(Rowlocks(tx))。当一个update发生在一个未压缩块中的行,只有这行被锁。与之不同的是,如果一个update发生在一个压缩单元中的行,则整个压缩单元中的所有行都会被lock。更新使用了混合列压缩rows的rowids的改变。

  注意:

  当表使用了混合列压缩,Oracle DML操作时会锁住 压缩单元(一大堆数据块),这样会降低并发

 

 

Overview of Table Clusters (TableCluster的概述)

Tablecluster 是一组表,这组表共享一些共有的列,并把相关的数据存储到相同的块.当表是clustered(集群化的),一个数据块可以包含多个表的行。

举个例子.一个块可以存放employees和departments表中的行,而不是只能存储一个表中的行。

clusterkey 是指集群化的表中的公共列。举个例子,employees和departments表分享department_id列.

你要在创建table cluster(表集群)和每个附加在tablecluster上的表时,要指定cluster key

clusterkey value 是指cluster key 列中的值。

所有包含cluster key value(比如department_id=20),都是物理存储在一起的。每个cluster key value在一个table cluster中只存储一次。无论有多少不同表都用了这个列。

打个比方,假设人事经理有两个书架:一个放着雇员信息文件的盒子,另一个放着装有部门文件的盒子.用户经常需要找一些特定部门的雇员信息。为了让检索更简单,这个经理把所有的盒子都放到一个书架。她把盒子根据部门ID分开,因此所有在部门20的雇员信息,以及部门20本身自己的信息都放入了一个盒子。而部门100的雇员信息和部门100自身的信息放入一个不同的盒子,以此类推

 

当表经常被查询(不经常修改),而且表频繁用join方式查询,这时候可以考虑用tablecluster而把表集群化起来(共享某些列)。因为table cluster可以存储不同表的相关列在一个数据块,

恰当的使用table cluster有下列优势(对比非集群化的表):

·集群化后的表(附加在tablecluster上的表)join的时候,磁盘I/O会减少。

·集群化后的表 join的时候,访问时间会有改善

·存储的使用会减少。因为clusterkey value 只存一次。N多表都可以用。

下列情况,使用cluster tables不合适:

·表经常被更新

·表经常需要 全表扫描

·表会被 truncate命令操作。

 

Indexes Clusters 概述

Indexedcluster是table cluster使用的索引。cluster index是在cluster key上的B*tree索引。一个cluster index必须在cluster key中没有数据的时候创建。

 

假设你创建了table cluster :employees_departments_cluster,cluster key是department_id,像下面语句显示,因为HASHKEYS子句没指定,则这个cluster是一个indexedcluster。之后你创建了一个名叫idx_emp_dept_cluster的索引在这个cluster key上。

CREATECLUSTER employees_departments_cluster

  (department_id NUMBER(4))

SIZE512;

CREATEINDEX idx_emp_dept_cluster ON CLUSTER employees_departments_cluster;

然后你创建employees和departments表到这个cluster中。指定department_id列为clusterkey.如下(省略号标记的位置是设置列的位置)

CREATETABLE employees(...)

         CLUSTERemployees_departments_cluster(department_id);

CREATETABLE departments(...)

         CLUSTERemployees_departments_cluster(department_id);

最后,你插入行到employees和departments。employees和departments表上,department_id相同的数据,会被物理的存储在一个块里。存储的格式是heap。访问它们通过index。

下图显示了employees_departments_clusterTABLE CLUSTER。它包含了employees和departments表。数据库将department20的雇员信息行存储在一起,department110的雇员信息行存储在一起,以此类推。

如果表没有集群化(notclustered,也就是普通表)数据库不保证相关的行会存储在一起。

 


B-treecluster index根据包含cluster key value的块的DBA(数据库块地址)进行关联。

举个例子:一个索引条目显示的数据块地址,这个数据块地址包含了department20的雇员信息。

20,AADAAAA9d

clusterindex是分开管理的。就像非clusterd表(普通表),它可以存入到一个与table cluster所在表空间不同的表空间

 

Overview of Hash Clusers 哈希cluster概述

hashcluster很像indexed cluster,除了将index key 替换为 hash function. 没有单独的cluster index..

在hash cluster中,数据本身就是index(索引)

在有索引的表 或者 indexedcluster,Oracle数据库通过存在索引中的key value来定位行.

为了找到存在表中的行,数据库最小都需要两个I/O

·一个(或更多)I/O用来找到索引中的keyvalue

·另外一个I/O用来读or写 表中或table cluster 中的行

 

在hash cluster中读取或写入一行,Oracle数据库 对 行的cluster key value 执行 hashfunction ,返回的hash值会对应到cluster中的一个数据块,这个块就是语句要读或着写的。

 

增强数据的检索能力,hash是一种选择。

Hashclusters在下列情况是有益处的

·这个表DML频繁

·hash key列经常在条件中用=号。例如 wheredepartment_id=20.像这种查询,cluster key values是hash的,这个hash key value 直接指向磁盘中存储这行的区域。

·你可以有根据的猜测 hash key的数量,以及每个 keyvalue存储了多少数据

 

HASH Cluster Creation  创建HASHCluster

hashcluster 的cluster key。和indexed cluster的cluster可以很像。

是一个段或者多个段。被cluster中的表所共享使用的。

hash keyvalues就是插入到cluster key column中的值

例如:如果cluster key 是department_id。则hash keyvalues 可能就是10,20,30以此类推

 

Oracle数据库使用hashfunction(函数),插入无数的 hash key values,分类它们然后插入到有数的buckets(桶)中。每个bucket都有一个唯一的数字ID,叫 hash value。

每个hash value 都是一张地图,上面记录了hashkey value对应行储存的块的地址。

 

使用CREATE CLUSTER语句创建hash cluster,附加一个hash key。hash values的数 取决于hash key。下面例子中,可能存在的部门数量为100个,所以 HASHKEYS 设置成100.

CREATECLUSTER employees_departments_cluster

(department_idNUMBER(4))

SIZE8192 HASHKEYS 100;

在创建employees_departments_cluster后,你可以创建employees和departments表到这个cluster中。你可以将数据加载进去。创建表的过程和 indexed cluster一模一样。

 

Hash Cluster Queries(hashcluster的查询)

数据库自己决定怎样把用户插入的keyvalue HASH掉(哈希),而不是某个用户来决定。

举例:假设用户频繁的执行像下面这样的查询。输入不同的department ID到p_id

SELECT *

FROMemployees

WHEREdepartment_id =:p_id;

 

SELECT *

FROMemployees

WHERE department_id=:p_id;

 

SELECT *

FROMemployees e,departments d

WHEREe.department_id = d.department_id

ANDd.department_id = :p_id;

如果用户查询在department_id等于20的雇员,则数据库会hash这个值(20)到bucket 77.

如果用户查询在department_id等于10的雇员,则数据库会hash这个值(10)到bucket 15.

数据库根据要查询的部门IP 使用内部产生hashvalue去定位包含empolyee行的块。

下图描述了一个hash cluster 段 是一堆水平的块,像显示的那样 ,查询可以一个I/O就检索到数据



hashclusters的限制是,如果cluster key没有进行索引,就无法进行 index range scan。假设它没有单独对hash cluster创建一个索引。而一个查询要查部门20到100,就必须进行全表扫描,而不能进行index range scan。因为hash算法没办法hash 20 到100之前的所有值(20-100之间有无数个值)。

 

Hash Cluster Variations (Hash Cluster 的变种)

单表hash cluster是最优化的hash cluster,它在同一时间只支持一个表存在。这时候hash key和row存在一一映射关系。

一个单表hash cluster 可以有效的用于用户通过主键快速查询这个单表。

举个例子:用户经常通过empolyees表中的empolyees_id主键来查找数据。

 

有序的hash cluster存储的行将根据hash key排序好,这样数据库就可以按照排序的顺序返回每个值对应的行。

数据库将在内部执行最优的排序.对于应用来说,它们总是消耗资源在数据库的排序上.这个技术可能意味着更快的查询数据.

举个例子:

一个应用可能总是根据orders表的order_date列进行排序.

 

Hash Cluster Storage(Hash cluster的存储)

 Oracle数据库分配hashcluster的空间,不同于indexed cluster


上面例子中,HASHKEYS指定了可能会存在的部门,而SIZE指定了每个部门的各自数据大小。

数据库基于下面的值计算出存储空间的大小:

HASHKEYS* SIZE /database_block_size

因此,如果上面例子中块大小是4K,那么数据库给hashcluster最少分配200个块.

Oracle 数据库并不限制你可以插入的hashkey values的数量。

举个例子:尽管 HASHKEYS是100..但是你可以是可以插入200个不同的部门到departments表.不过,如果hash values的值超过了HASHKEYS,则检索速度会受到影响.

图解说明一下检索的的问题,在下图中假设块100存满了department20的行。一个用户插入一个department_id是43的新部门。部门的数量超过了HASHKEYS的值。那么数据库将把部门43 hash为77,而77和部门20hash的值一样。

将不同的值hash成相同的值,有个术语叫哈希冲突。

当用户插入部门43的相关行,则数据库不能存储这些行到块100(已经放满了部门20的数据)。数据库将发生overflow,连接一个新块到块100,这个新块叫块200,并将数据插入到这个块。这时候块100和200将存储两个部门中的值。像下图显示的,一次查询,无论查询20还是43,现在都需要两个I/O才可以返回数据。块100和块200进行了关联。你可以通过重新创建一个新的cluster,增加HASHKEYS值来解决这个问题。



---------------------------------------------------------------------------------------

勤学如春起之苗,不见其增日有所长。辍学如磨刀之石,不见其损日有所亏

 

Email:    orahank.dai@gmail.com

QQ:       88285879



;