Oracle 基础表管理(Heap-Organized Table Management)

表是数据库中负责数据存储的对象,在RDBMS中,数据以行、列的形式存储在表中。Oracle中表有很多种类型,最基础且应用最常用的类型就是堆表(Heap-Organized Table),本文列举了Oracle堆表的常用管理操作。

一、表的类型简介

数据可以有不同的组织形式,生命周期等特点,面对不同的数据存储场景需求,Oracle提供了很多类型的表,主要类型有:

  • 堆表(Heap-Oragnized Tables)
  • 索引组织表(Index-Organized Tables)
  • 分区表(Partitioned Tables)
  • 外部表(External Tables)
  • 聚簇表(Clustered Tables)

根据表的其他特点还可以划分出临时表(Temporary Tables)、不可变表(Immutable Tables),区块链表(Blockchain Tables)等。

而堆表(Heap-Organized Tables)是Oracle种最基础的数据存储对象,之所以叫做堆表是由于其底层存储的数据结构是堆(Heap,一种无序的数据集合)。当使用create table创建表时,默认创建的就是堆表。

二、表的创建方法

表在逻辑上由行(Row)和列(Column)组成,在创建一张表时,需要定义下列内容:

  • 表名
  • 一个或多个列(列的定义至少包含列名和数据类型,也可以从已有表复制定义)
  • 表的其他属性(分区、存储、类型等等),这些是可选项,如果没有特殊指定,Oracle会按默认配置创建表。

2.1 使用create table语句创建表

表由create table语句创建,创建一个最简单的表,只需要指定表名,列名(列的数据类型)即可:

create table mytab (
id int,
name varchar2(32));

在这里插入图片描述
上面示例中我们仅指定了最少信息,实际上表还有许多其他属性,可以用dbms_metadata.get_ddl来查询表的DDL语句:

select dbms_metadata.get_ddl('TABLE','MYTAB') from dual;

在这里插入图片描述
可以看到实际存储的定义比我们指定的复杂的多,由于很多属性没有显式指定,所以它们都是默认值:

  • 表名变成了hr.mytab,这里使用hr用户连接,因此表创建在该用户的默认schema中(create any table权限可以在别人的schema中创建表)。
  • int类型显示的是number(*,0),int实际是number的子类型,小数部分为0。
  • segment creation deffered,段延迟创建,即仅创建了表定义,实际存储数据的段会在第一条数据插入时才创建(可以节省空间,特别是存在大量小表的环境)。与之对应的选项是segment creation immediate, 创建表定义时,同时分配存储段。
  • pctfree 10 pctused 40 是数据块容量使用策略,普通用户不建议调整。
  • initrans 1 maxtrans 255 是事务数量管理
  • nocompress 表内数据不压缩
  • logging 表上操作的记录redo日志
  • tablespace “users” 表创建在users表空间

注:schema是Oracle为每个用户分配的一个对象逻辑容器(和用户名相同),当某个用户创建数据库对象时,默认就会创建在自己的schema中。你可以把它当作一个命名空间,不同schema中的同名对象不会冲突,可以使用schema.object_name的命名方式来引用对象。

除了让Oracle自动创建和管理数据段,还可以使用storage子句来自己指定表的物理存储属性(指定表的初始/最大大小):

create table mytab2 (
id int,
name varchar2(32))
storage (initial 12m next 4m maxsize 1G);

在这里插入图片描述

  • 这里使用storage子句指定表初始大小为12m,每次扩展大小为4m,最大为1G

2.2 复制已有表定义

create table …. as select ….; 语句可以复制一张已存在的表定义,这个语句包含2个部分,建表部分create table (DDL)和查询部分select(DML)。

下面语句从employees表复制一张employees_copy,仅复制表结构,不填充数据:

create table employees_copy as select * from employees where 1=2;

  • where 1=2 是一个永远无法成立的条件,所以不会复制数据,去除该条件则所有数据也将填充到新表中。
  • select * 代表复制所有的列,也可以显式的指定列名(复制过程中也可以修改列名),仅复制部分表结构。

2.2.1 使用nologging提升复制性能

使用create table … as select …; 语句复制一张表并填充数据时,如果表的数据量非常大,那么复制的操作可能给系统带来比较大的压力。在复制时使用nologging选项可以提升性能,nologging会减少数据复制时生成的redo日志(从源表复制数据,redo日志并不重要,就算操作失败了重新复制就行)。

而且nologging选项仅影响create table时数据复制操作(不影响表本身的logging属性),后续该表上的insert,update语句都会正常生成redo日志,不用担心崩溃时数据会丢失:

create table employees_copy2 as select * from employees nologging;

在这里插入图片描述

三、表基础维护

表在创建后经常随着业务需求进行调整,表的可变更选项非常多,这些变更选项可以在create table时指定,也可以在表创建完成后通过alter table修改。

3.1 新增/修改/删除/重命名列

列的定义通常是变更最频繁的,随着业务的需求的变化经常需要对列的属性进行修改。

3.1.1 新增列

alter table …. add [column] … 语句可以在表中新增列,新增时需要指定列的名称,数据类型等其他属性(和建表时相同)。当一个新的列被添加至表中,已有数据该列上的值都是null,你也可以指定default,为已有的数据填充默认值。

alter table mytab add salary number(8,2) default 1000;
alter table mytab add bonus number(8,2);

在这里插入图片描述

  • 示例为表mytab新增了salary和bonus列,其中salary列指定了默认值属性(默认1000)
  • 表中已有数据salary列都被更新为默认值1000,而bonus列全部为null

3.1.2 修改列

修改列是对已有数据列定义的更新,例如数据类型,大小,默认值等,语法和新增列基本相同,只是将关键字add替换为modify。

alter table mytab modify salary number(10,2) not null;

在这里插入图片描述

  • 示例将salary列的数据类型修改为number(10,2) 删除了default属性,新增了not null约束

3.1.3 删除列

通过 alter table … drop … 可以删除1个或多个列,删除列时,列的定义及数据都会被清除,存储空间会被回收,注意在大表此操作可能会影响性能:

alter table mytab drop column bonus;

在这里插入图片描述

3.1.4 重命名列

通过alter table …. rename column … to …语句可以重命名指定列,同时对该列上的依赖对象(函数索引,check约束等)Oracle也会自动进行更新并保持有效。

alter table mytab rename column salary to salary2;

在这里插入图片描述

3.2 不可用列

在3.1.3中提到,删除某列时会清除该列数据,如果表的数据量非常大,这个操作可能会占用大量系统资源,造成性能下降。Oracle提供了另一个折中的方案:先将列标记为不可用(逻辑删除),等待系统负载较轻时再清除数据(物理删除)。当列被标记为不可用时,它不会被select查询查出来,对于应用来说该列仿佛真的被删除了(你甚至可以重用列名)。

使用 alter table …. set unused … 将某1列或多列标记为不可用,注意列一旦被标记为不可用之后就无法恢复了,后续只能将其删除:

alter table mytab set unused(salary2);

在这里插入图片描述

  • 示例将salary2列标记为不可用,select语句不再能查出该列
  • 后续又新增了一个同名salary2列,也不会冲突

将列标记为不可用后,通过视图dba/all/user_unused_col_tabs可以查看表上不可用列的数量:

select * from user_unused_col_tabs where table_name='MYTAB';

在这里插入图片描述

待系统空闲时,使用 alter table … drop unused columns [checkpoint 300]; 物理清除该列的数据并回收空间(使用dorp column显式删除其他列时,不可用列也会被一并删除)。可选的checkpoint子句可以指定清理多少行执行一次检查点(示例中是300),防止在大表上操作时undo表空间过度扩张:

alter table mytab drop unused columns checkpoint 300;

在这里插入图片描述

  • 删除不可用列后,通过user_unused_col_tabs可以看到该列已经真正被删除了(清理数据)

3.3 隐形列

Oracle隐形列,可以将列对应用隐藏起来,但可以显式调用。例如应用升级前,可以预先对数据库升级,升级中新增的列设置为隐形,不影响当前应用。隐形列可以通过显式指定列名来查询和更新(select */ desc等命令不会显式)。和不可用列只能删除不同,隐形列你可以随意在隐藏和显示两种状态间切换。

隐形列的使用方法可以参考下面的文章:
Oracle 隐形列(Oracle Invisible Columns)

3.4 虚拟列

Oracle虚拟列是没有实际存储数据的,它的值是基于实体列计算而来,所以你不能更新虚拟列,但可以像正常的列一样查询它(虚拟列的值只有在查询时才会进行计算)。虚拟列只能在普通的堆表上使用,例如索引组织表,外部表,临时表等都是不支持虚拟列的。

虚拟列通过as关键字创建,以包含实体列的表达式定义(虚拟列不能引用其他虚拟列):

alter table mytab add salary number(8,2) default 1000;
alter table mytab add income as (salary*1.1);    -- 基于salary列的虚拟列

在这里插入图片描述

  • 示例中新增了实体列salary,随后基于salary新增了虚拟列income,并将值提升了10%

当实体列被虚拟列引用时是无法直接删除的,必须先删除虚拟列:

alter table mytab drop column salary;

在这里插入图片描述

  • 删除被虚拟列引用的实体列会报错

3.5 移动表至新表空间

用alter table … move [online] tablespace …可以将表移动至新表空间,新表空间可能放在不同的存储设备上,用于均衡I/O负载。online是可选关键字,如果指定则表上运行的DML语句在移动过程中不会被阻塞。

下面将表移动至新表空间new_tbs:

alter table mytab move online tablespace new_tbs;

在这里插入图片描述

  • 这里切换至sys用户,新建了new_tbs表空间(hr用户没权限)
  • 随后切换至hr用户,将表在线移动至new_tbs表空间

3.6 只读模式

alter table … read only/write 可以将表在只读/读写模式之间切换。当表在只读模式下,会禁止一切DML更新或截断表(truncate table),也不可以重命名或删除列,但是会允许新增/修改列,以及对索引,约束等不影响数据的对象进行操作。

对于一些配置表,若表中数据不经常变动,那么非常适合将其置于只读模式来防止程序对其进行意外修改:

alter table mytab read only;
alter table mytab read write;

在这里插入图片描述

四、闪回删除

Oracle在执行drop table命令时,并不会直接删除表,而是将其重命名并放入回收站(Recyclebin),如果用户发现误删,可以用闪回删除功能将表恢复(相关索引、约束、触发器等也会一并恢复)。注意只有在drop table命令才可以使用闪回删除,其他例如truncate table, drop user, drop tablespace这些操作都会直接清除表或数据。

闪回删除的具体操作方法可以参考下面文章:
Oracle闪回技术详解及应用

五、闪回表

闪回表的原理是利用undo日志,将整张表的状态(数据)回退到过去某个时间点/SCN/restore_point。该时间点之后的所有变更都会被撤销,而数据库其他的部分不受影响。闪回删除针对的是表这个对象误删除的闪回,而闪回表针对的是表内数据的闪回。

闪回表的具体操作方法可以参考下面文章:
Oracle闪回技术详解及应用

六、常用视图

Oracle提供了一系列数据字典视图,方便查询表的相关信息。视图以dba, all, user开头,分别代表全部/可查看/归属本用户的表信息,只是数据范围不同,部分常用视图列举如下:

  • dba/all/user_tables: 查询表的基本信息
  • dba/all/user_tab_columns: 查询列的基本信息
  • dba/all/user_tab_comments: 查询表和视图的备注信息
  • dba/all/user_col_comments: 查询表和视图的列的备注信息
  • dba/all/user_tab_statistics: 查询表的统计信息(优化器使用)
  • dba/all/user_unused_col_tabs: 查询表中被标记不可用的列

相关阅读:
Oracle分区表详解(Oracle Partitioned Tables)

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值