【数据库管理】①② Oracle逻辑存储架构(上)
1. 表的介绍
1.1 表的功能
表是关系型数据库中最基本的数据存储结构,它由行和列组成,每一行代表一个记录,每一列代表一个字段。表的主要功能包括:
存储数据:表是关系型数据库中最基本的数据存储结构,它可以存储各种类型的数据,如文本、数字、日期等。
组织数据:表可以将数据按照一定的结构和规则进行组织,使得数据更加有序、清晰、易于管理和维护。
检索数据:表可以通过SQL语句进行检索,根据条件查询所需的数据,方便用户获取所需的信息。
更新数据:表可以通过SQL语句进行更新,添加、修改或删除数据,保证数据的准确性和完整性。
约束数据:表可以通过约束条件限制数据的输入和修改,保证数据的一致性和完整性。
关联数据:表可以通过外键关联其他表的数据,实现数据的关联和查询。
表是关系型数据库中最基本的数据存储结构,它可以存储、组织、检索、更新、约束和关联数据,是数据库管理和应用的核心。
1.2 表的类型
在关系型数据库中,表的类型主要包括以下几种:
普通表:普通表是最常见的表类型,它包含多个列和多行数据,每个列代表一个字段,每行代表一个记录。
临时表:临时表是一种临时性的表,它只在当前会话中存在,当会话结束时,临时表也会被删除。临时表通常用于存储临时数据,如中间结果、临时计算等。
系统表:系统表是数据库系统内部使用的表,它包含了数据库的元数据信息,如表结构、索引信息、用户信息等。系统表通常由数据库管理系统自动创建和维护,用户无法直接访问和修改。
视图:视图是一种虚拟的表,它不存储数据,而是基于一个或多个表的查询结果生成的。视图可以简化复杂的查询操作,提高查询效率,同时也可以保护数据的安全性和隐私性。
分区表:分区表是一种特殊的表,它将数据按照一定的规则分成多个分区存储,每个分区可以独立管理和维护。分区表可以提高查询效率,同时也可以方便数据的管理和维护。
外部表:外部表是一种特殊的表,它不存储数据,而是通过外部数据源(如文件、数据库、Web服务等)访问数据。外部表可以方便地将外部数据集成到数据库中,同时也可以提高数据的安全性和可靠性。
历史表:历史表是一种用于存储历史数据的表,它可以记录数据的变化历史,包括数据的创建、修改和删除等操作。历史表可以用于数据审计、数据分析和数据恢复等方面。
全局临时表:全局临时表是一种全局性的临时表,它可以被多个会话共享,直到所有会话结束时才会被删除。全局临时表通常用于多个会话之间共享临时数据。
堆表:堆表是一种没有聚集索引的表,数据按照插入顺序存储,没有特定的排序方式。堆表通常用于临时存储数据或者数据仓库中的中间表。
分布式表:分布式表是一种分布式数据库中的表,它可以跨多个节点进行分布式存储和查询。分布式表可以提高数据库的可扩展性和性能。
虚拟表:虚拟表是一种特殊的表,它不存储数据,而是通过程序动态生成的。虚拟表通常用于存储计算结果、中间结果或者临时数据。
存储过程表:存储过程表是一种存储过程返回的结果集,它可以像普通表一样进行查询和操作。存储过程表通常用于存储复杂查询的结果,或者将存储过程的结果集作为其他查询的输入。
全文索引表:全文索引表是一种用于全文搜索的表,它可以对表中的文本数据进行全文索引,提高搜索效率和准确性。
多维表:多维表是一种用于OLAP(联机分析处理)的表,它可以将数据按照多个维度进行分析和查询,如时间、地区、产品等。多维表通常用于数据分析和决策支持等方面。
自定义表类型:自定义表类型是一种用户自定义的表类型,它可以定义表的结构和数据类型,然后在存储过程、函数或者其他对象中使用。自定义表类型通常用于存储复杂数据结构或者作为存储过程的参数或返回值。
元数据表:元数据表是一种用于存储数据库元数据信息的表,它包含了数据库对象的定义、属性、关系等信息。元数据表通常由数据库管理系统自动创建和维护,用户可以通过查询元数据表获取数据库对象的信息。
空表:空表是一种没有数据的表,它可以用于存储表结构或者作为其他表的基础表。空表通常用于数据模型设计、数据迁移等方面。
1.3 普通表转换为分区表
将普通表转换为分区表的过程需要经过以下几个步骤:
创建分区函数:分区函数是用于将表数据按照一定规则分成多个分区的函数,可以根据不同的需求选择不同的分区函数,如按照时间、地区、产品等进行分区。例如,可以使用日期范围来定义分区函数,将表数据按照日期范围分成多个分区。
创建分区方案:分区方案是用于定义分区表的分区方式和分区键的方案,可以根据不同的需求选择不同的分区方案,如按照时间、地区、产品等进行分区。例如,可以使用日期范围来定义分区方案,将表数据按照日期范围分成多个分区。
创建分区表:创建分区表时需要指定分区方案和分区函数,以及其他表的属性和约束条件。例如,可以使用CREATE TABLE语句创建分区表,指定分区方案和分区函数,如下所示:
CREATE TABLE sales ( sale_id INT PRIMARY KEY, sale_date DATE, sale_amount DECIMAL(10,2) ) PARTITION BY RANGE (sale_date) ( PARTITION p1 VALUES LESS THAN ('2020-01-01'), PARTITION p2 VALUES LESS THAN ('2020-02-01'), PARTITION p3 VALUES LESS THAN ('2020-03-01'), PARTITION p4 VALUES LESS THAN ('2020-04-01') );
- 导入数据:将原来的普通表数据导入到分区表中,可以使用INSERT INTO语句或者其他数据导入工具进行导入。
在 Oracle 19c 中,将普通表转换为分区表的过程需要经过以下几个步骤:
- 创建分区函数:使用 CREATE OR REPLACE FUNCTION 语句创建分区函数,例如:
CREATE OR REPLACE FUNCTION sales_date_partition(date_value DATE) RETURN VARCHAR2 AS BEGIN RETURN TO_CHAR(date_value, 'YYYY-MM'); END; /
上述分区函数将日期值转换为字符串格式的年月,用于按照年月进行分区。
- 创建分区方案:使用 CREATE TABLE 语句创建分区表时,需要指定分区方案,例如:
CREATE TABLE sales ( sale_id NUMBER(10), sale_date DATE, sale_amount NUMBER(10,2) ) PARTITION BY RANGE (sale_date) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH')) ( PARTITION p0 VALUES LESS THAN (TO_DATE('2020-01-01', 'YYYY-MM-DD')) );
上述分区方案按照 sale_date 列进行分区,每个分区的时间跨度为一个月,使用 INTERVAL 子句指定分区间隔,使用 PARTITION 子句指定第一个分区的范围。
- 导入数据:使用 INSERT INTO 语句或其他数据导入工具将原来的普通表数据导入到分区表中,例如:
INSERT INTO sales (sale_id, sale_date, sale_amount) SELECT sale_id, sale_date, sale_amount FROM sales_old;
上述语句将 sales_old 表中的数据导入到 sales 表中。
2 堆表HOT
在数据库中,堆表(Heap Table)是一种没有聚集索引的表,数据按照插入顺序存储,没有特定的排序方式。由于没有聚集索引,堆表的数据存储方式比较简单,插入数据的速度也比较快,但是查询数据的速度较慢,因为需要进行全表扫描。
为了提高堆表的查询性能,可以使用堆表热点(Heap-Organized Tables with no Clustered Index,HOT)技术。堆表热点技术是一种基于堆表的索引技术,它可以在堆表中创建一个非聚集索引,用于加速查询热点数据。
堆表热点技术的实现方式是,在堆表中创建一个非聚集索引,该索引只包含热点数据的引用,而不是所有数据的引用。热点数据是指经常被查询的数据,可以根据具体的业务需求进行定义。当查询热点数据时,可以先通过非聚集索引找到热点数据的引用,然后再通过引用访问堆表中的数据,从而提高查询性能。
堆表热点技术的优点是可以提高查询热点数据的性能,同时不会影响插入数据的性能。缺点是需要额外的索引空间和维护成本,同时对于非热点数据的查询性能仍然较低。
堆表热点技术(HOT)是一种基于堆表的索引技术,可以提高查询热点数据的性能,适用于查询频繁、插入不频繁的场景。
3 分区表
分区表是一种将表数据按照一定规则分成多个分区的表,每个分区可以独立进行管理和查询。分区表可以提高查询效率和管理数据的灵活性,适用于大型数据集和高并发访问的场景。
根据分区规则的不同,分区表可以分为以下几种类型:
范围分区表(Range Partitioned Table):按照某个范围进行分区,例如按照时间、价格、地区等进行分区。
列分区表(List Partitioned Table):按照某个列的值进行分区,例如按照产品类型、客户类型等进行分区。
哈希分区表(Hash Partitioned Table):按照某个列的哈希值进行分区,可以均匀地分配数据到各个分区中。
复合分区表(Composite Partitioned Table):按照多个分区键进行分区,例如按照时间和地区进行分区。
自定义分区表(Reference Partitioned Table):按照其他表的分区方式进行分区,例如按照订单表的分区方式进行分区。
分区表优势:
提高查询效率:分区表可以将数据分散到多个分区中,查询时只需要扫描相关分区,可以大大提高查询效率。
提高数据管理的灵活性:分区表可以根据不同的需求选择不同的分区方式,例如按照时间、地区、产品等进行分区,可以更加灵活地管理数据。
提高数据安全性:分区表可以将敏感数据存储在独立的分区中,可以提高数据的安全性。
提高数据可用性:分区表可以使用分区交换、分区合并等技术,可以在不影响业务的情况下进行数据维护和升级,提高数据的可用性。
提高并发访问能力:分区表可以将数据分散到多个分区中,可以提高并发访问能力,减少锁竞争和死锁等问题。
3.1.2 范围分区Range Partitioning
3.1.2.1 概述
范围分区表(Range Partitioned Table)是一种按照某个范围进行分区的表,例如按照时间、价格、地区等进行分区。范围分区表可以提高查询效率和管理数据的灵活性,适用于大型数据集和高并发访问的场景。
3.1.2.2 语法
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
...
)
PARTITION BY RANGE (column_name) (
PARTITION partition_name1 VALUES LESS THAN (value1),
PARTITION partition_name2 VALUES LESS THAN (value2),
...
);
3.1.2.3 创建分区表
CREATE TABLE sales (
sale_id NUMBER(10),
sale_date DATE,
sale_amount NUMBER(10,2)
)
PARTITION BY RANGE (sale_date) (
PARTITION p1 VALUES LESS THAN (TO_DATE('2020-01-01', 'YYYY-MM-DD')),
PARTITION p2 VALUES LESS THAN (TO_DATE('2020-02-01', 'YYYY-MM-DD')),
PARTITION p3 VALUES LESS THAN (TO_DATE('2020-03-01', 'YYYY-MM-DD')),
PARTITION p4 VALUES LESS THAN (TO_DATE('2020-04-01', 'YYYY-MM-DD'))
);
上述语句创建了一个名为 sales 的范围分区表,按照 sale_date 列进行分区,分为 p1、p2、p3、p4 四个分区,分区值分别为 2020-01-01、2020-02-01、2020-03-01、2020-04-01。
范围分区表可以提高查询效率和管理数据的灵活性,可以根据不同的需求选择不同的分区方式,例如按照时间、价格、地区等进行分区。
3.1.2.4 查看信息
SQL> select * from user_tab_partitions where table_name='SALE';
col table_name for a10
col high_value for a10
SQL> select table_name,partition_name,high_value from user_tab_partitions where table_name='SALE';
TABLE_NAME PARTITION_NAME HIGH_VALUE
---------- -------------- ------------
SALE P1 1000
SALE P2 2000
SALE P3 3000
3.1.2.5 插入数据
insert into sale values('1',600);
1 row created.
insert into sale values('2',1000);
1 row created.
insert into sale values('3',2300);
1 row created.
insert into sale values('4',6000);
SQL> insert into sale values('4',6000);
insert into sale values('4',6000)
ERROR at line 1:
ORA-14400: inserted partition key does not map to any partition
commit;
3.1.2.6 查看范围分区数据
select * from sale partition(p1);
select * from sale partition(p2);
3.1.2.7 增加maxvalue分区
alter table sale add partition p4 values less than(maxvalue);
SQL> select table_name,partition_name,high_value from user_tab_partitions where table_name='SALE';
TABLE_NAME PARTITION_NAME HIGH_VALUE
---------- -------------- ------------
SALE P1 1000
SALE P2 2000
SALE P3 3000
SALE P4 MAXVALUE
3.1.2.8 插入新分区的值
SQL> insert into sale values('4',6000);
SQL> select * from sale partition(p4);
PRODU SALES_COUNT
----- -----------------
4 6000
3.1.2.9 查看段的分配
SQL> col segment_name for a15
SQL> col partition_name for a15
SQL> select segment_name,segment_type,partition_name from user_segments;
SEGMENT_NAME SEGMENT_TYPE PARTITION_NAME
------------ ------------------ --------------
DEPT TABLE
EMP TABLE
PK_DEPT INDEX
PK_EMP INDEX
PRODUCTS TABLE
SALE TABLE PARTITION P1
SALE TABLE PARTITION P2
SALE TABLE PARTITION P3
SALE TABLE PARTITION P4
SALGRADE TABLE
3.1.2.10 跨分区操作报错处理
默认情况下,如果对分区表的分区字段做超范围(跨段p1,p2,p3,p4)update操作,会报错—— ORA-14402: .
如果一定要改,可以通过打开表的row movement属性来完成.
SQL> select * from sale;
PRODU SALES_COUNT
----- ---------------
1 600
2 1000
3 2300
4 6000
3.1.2.10.1 跨分区更改失败
SQL> update sale set sales_count=1200 where sales_count=600;
update sale set sales_count=1200 where sales_count=600
ERROR at line 1:
ORA-14402: updating partition key column would cause a partition change
-- ORA-14402: 更新分区关键字列将导致分区的更改
3.1.2.10.2 查询要更改数值当前rowid
SQL> select rowid,t1.* from sale partition(p1) t1;
ROWID PRODU SALES_COUNT
------------------ ------ ------------
AAAXWQAAGAAAAVvAAA 1 600
3.1.2.10.3 使能row movement
QL> alter table sale enable row movement;
SQL> update sale set sales_count=1200 where sales_count=600;
已更新 1 行.
SQL> select rowid,t1.* from sale partition(p2) t1;
ROWID PRODU SALES_COUNT
------------------ ------ ------------
AAASvVAAEAAAAGdAAA 2 1000
AAAXWRAAGAAAAlvAAB 1 1200
般来说范围分区的分区字段使用数字类型或日期类型,使用字符类型的语法是可以的,实际工作中使用较少.这或许跟values less than子句有关.
3.1.3 散列分区Hash Partitioning (也叫hash分区)
3.1.3.1 概述
散列分区(Hash Partitioning)是一种按照某个列的哈希值进行分区的表,可以均匀地分配数据到各个分区中。散列分区可以提高查询效率和管理数据的灵活性,适用于大型数据集和高并发访问的场景。
散列分区通过在分区键值上执行一个散列函数来决定数据的物理位置.
(散列分区是根据字段的hash值进行均匀分布,尽可能的实现各分区所散列的数据相等)
在范围分区中,分区键的连续值通常储存在相同的分区中.而在散列分区中,连续的分区键值不必储存在相同的分区中.
散列分区把记录分布在比范围分区更多的分区上,这减少了I/O争用的可能性,实现均匀的负载值分配,增加HASH分区可以重新分布数据.
3.1.3.2 语法
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
...
)
PARTITION BY HASH (column_name) (
PARTITION partition_name1,
PARTITION partition_name2,
...
);
其中,table_name 是表名,column1、column2 等是列名和数据类型,column_name 是用于分区的列名,partition_name1、partition_name2 等是分区名称。
3.1.3.3 创建散列分区
SQL>
create table my_emp(empno number, ename varchar2(10))
partition by hash(empno)
(
partition p1,
partition p2
);
3.1.3.4 查看信息
SQL> select * from user_tab_partitions where table_name='MY_EMP';
SQL> col table_name for a10
SQL> select table_name,partition_name from user_tab_partitions where table_name='MY_EMP';
TABLE_NAME PARTITION_NAME
---------- ---------------
MY_EMP P1
MY_EMP P2
3.1.3.5 插入数据
SQL>
insert into my_emp values(1,'A');
insert into my_emp values(2,'B');
insert into my_emp values(3,'C');
3.1.3.6 查询散列分区数据
SQL> select * from my_emp partition(P1);
EMPNO ENAME
----- ----------
2 B
SQL> select * from my_emp partition(P2);
EMPNO ENAME
----- ----------
1 A
3 C