分区概述

来源:互联网 发布:掌上大学无法连接网络 编辑:程序博客网 时间:2024/05/03 18:59

分区使你能够将非常大的表和索引分解成更小、 更易于管理的叫做分区的片断。每个分区是一个独立的对象,具有其自己的名称和 (可选的)的存储特征

从应用程序的角度来看,只有一个模式对象已存在。DML 语句不需要作任何修改就可以访问该分区表。分区对许多不同类型的应用程序都很有用,特别是那些管理大量数据的应用程序。其好处包括:

 可用性增强

其中某个分区不可用并不意味着整个对象不可用。当部分分区不可用时,查询优化器自动从查询计划中删除未引用的分区,而查询不会受影响。

 更轻松的管理模式对象

已分区对象具有多个分片,可以将其作为一个整体来管理,也可以单独管理各个分片。DDL 语句可以处理分区,而不是整个表或索引。因此,您可以分解大量占用资源的任务,如重建索引或表。例如,您可以一次只移动一个表分区。如果发生了问题,则只需重新移动该分区,而不是整个表。而且,删除一个分区可以避免执行许多 DELETE 语句。

 在OLTP 系统中减少对共享资源的争用

在一些OLTP 系统中,分区可以减少对共享资源的争用。例如, DML 被分散到很多段,而不只是一个段。

 在数据仓库中增强的查询性能

在数据仓库中,分区可以加快处理即席查询。例如,包含一百万行的销售表可以按季度进行分区。

分区特征

每个表或索引的分区必须具有相同的逻辑属性,如列名称、 数据类型、和约束。例如,在一个表中的所有分区都共享相同的列和约束定义,并在索引中的所有分区都共享相同的索引列。但是,每个分区可以有单独的物理属性,如其所属的表空间。

分区键

分区键是一个列或列集,以确定分区表中的每一行应该所在的分区。每个行会被确定地(而不是模棱两可地)分配到某个分区。

分区策略

Oracle 分区提供了几个分区策略,来控制数据库如何将数据放置到分区基本策略有范围分区、 列表分区、和哈希分区等。

单一分区策略只使用一种数据分布方法,例如,仅使用列表分区,或仅使用范围分区。在复合分区中,表先按一种数据分布方法分区,然后每个分区使用第二种数据分布方法进一步分成子分区。例如,您可以使用 channel_id划分列表分区,并使用 time_id 划分范围子分区。

范围分区

在范围分区中,数据库基于分区键的值范围将行映射到各个分区。范围分区是最常见的分区类型,通常与日期一起使用。

假设您要用示例4-1中所示的销售行填充分区表。

这里写图片描述

使用示例 4-2 中的语句创建分区表 time_range_sales。time_id 列是分区键。

示例4-2 范围分区表

CREATE TABLE time_range_sales( prod_id NUMBER(6), cust_id NUMBER, time_id DATE, channel_id CHAR(1), promo_id NUMBER(6), quantity_sold NUMBER(3), amount_sold NUMBER(10,2))PARTITION BY RANGE (time_id)(PARTITION SALES_1998 VALUES LESS THAN (TO_DATE('01-JAN-1999','DD-MON-YYYY')),PARTITION SALES_1999 VALUES LESS THAN (TO_DATE('01-JAN-2000','DD-MON-YYYY')),PARTITION SALES_2000 VALUES LESS THAN (TO_DATE('01-JAN-2001','DD-MON-YYYY')),PARTITION SALES_2001 VALUES LESS THAN (MAXVALUE));

然后,您可以将示例4-1中的示例行加载到time_range_sales 表。图 4-1 显示了四个分区中的行分布。数据库根据PARTITION BY RANGE子句中指定的规则,基于 time_id 值为每个行选择适当的分区。

这里写图片描述

范围分区键值确定各个范围分区的高值,被称为跃点。在图 4-1中,分区SALES_1998包含分区键 time_id 值小于跃点 01-JAN-1999的行。

数据库为超出跃点的数据创建间隔分区。当插入到表中的数据超出所有已定义的表分区时,间隔分区指示数据库自动创建特定范围或特定间隔的分区,来扩展范围分区。在图 4-1 中,分区SALES_2001包含分区键 time_id 值大于或等于 01-JAN-2001的行。

列表分区

在列表分区中,数据库使用一些具体值的列表作为每个分区的分区键。你可以使用列表分区来控制单个行如何映射到特定的分区。当用来区分数据集的键不方便排序时,可以通过使用列表来分组和组织相关的数据集。

假设您使用示例 4-3 中的语句创建列表分区表list_sales。channel_id 列为分区键。

CREATE TABLE list_sales( prod_id NUMBER(6), cust_id NUMBER, time_id DATE, channel_id CHAR(1), promo_id NUMBER(6), quantity_sold NUMBER(3), amount_sold NUMBER(10,2))PARTITION BY LIST (channel_id)(PARTITION even_channels VALUES (2,4),PARTITION odd_channels VALUES (3,9));

随后,将示例4-1中的表行加载到表中。图 4-2 显示了在两个分区中的行分布。数据库根据PARTITION BY LIST子句中指定的规则,基于channel_id为每个行选择适当的分区。channel_id 值为 2 或 4 的行存储在 EVEN_CHANNELS 分区中,而 channel_id 值 为3 或 9的行存储在 ODD_CHANNELS 分区中。

这里写图片描述

哈希分区

在哈希分区中,基于用户所指定的将在分区键上应用的哈希算法,数据库将行映射到各个分区。行的目标分区是由数据库应用于行的内部哈希函数所决定的。哈希算法被设计为可以跨设备均匀分布行,以使每个分区包含大致相同的行数。

哈希分区可用于划分大表,以提高可管理性。你只需管理几个较小的表片断,而不是管理一个大型表。一个哈希分区的缺失并不影响其余分区,并且可以独立地恢复。在更新争用较高的 OLTP 系统中,哈希分区也是非常有用的。例如,一个段被分为几个片断,每个片断都可以被更新,而不像单个段那样会遭受争用。

假定您使用示例 4-4 中的语句创建hash_sales分区表。prod_id 列为分区键。

CREATE TABLE hash_sales( prod_id NUMBER(6), cust_id NUMBER, time_id DATE, channel_id CHAR(1), promo_id NUMBER(6), quantity_sold NUMBER(3), amount_sold NUMBER(10,2))PARTITION BY HASH (prod_id)PARTITIONS 2;

随后,将示例4-1中的表行加载到表中。图 4-3 显示两个分区中可能的行分布。请注意这些分区的名称是系统自动生成的

当您插入行时,数据库会尝试随机、 均匀地将它们分布在各个分区之间。您不能指定某行被放置在哪一个分区。数据库应用哈希函数,其结果确定由哪个分区包含此行。如果重新更改了分区数目,那么数据库会在所有分区上重新分布数据

这里写图片描述

查看HASH分区名称:

select partition_name from user_segments where segment_name = 'HASH_TABLE_NAME';

分区表

分区表包含一个或多个分区,它们可以单独进行管理,并且可以独立于其他分区进行操作表要么是分区表,要么是未分区表。即使分区表只包含一个分区,此表也是与一个未分区表不同的,不能将分区加入到未分区表中

分区表由一个或多个表分区段组成。如果您创建了一个名为 hash_products 的分区表,但并没有为此表分配表段。相反,数据库将每个表分区的数据存储在其自己的分区段中。每个表分区段包含表数据的一部分。

堆组织表中的某些分区或所有分区可以存储为压缩格式压缩可以节省空间,并可以加快执行查询的速度。因此,压缩可用于在插入和更新操作很少的数据仓库环境中,也可以用于 OLTP 环境中

可以为表空间、 表、或表分区声明表压缩属性如果在表空间级别声明,则默认情况下在该表空间中创建的表是被压缩的。您可以更改一个表的压缩属性,在这种情况下,此更改仅适用于插入到该表的新数据。因此,一个单表或分区可能包含压缩和未压缩的块,它保证数据的大小不会因为压缩反而增大如果压缩会增加一个数据块的大小,那么数据库就不压缩该块

创建复合索引示例:

create table test (prod_id NUMBER(6), cust_id NUMBER, time_id DATE, channel_id CHAR(1), promo_id NUMBER(6), quantity_sold NUMBER(3), amount_sold NUMBER(10,2))partition by list (cust_id)subpartition by range(time_id)(partition cust_id_1_2 values  (1,2) tablespace users(subpartition time_id_1999 values less than(to_date('1999-01-01', 'yyyy-mm-dd')),subpartition time_id_2000 values less than(maxvalue)) ,partition cust_id_3_4 values (3,4)(subpartition time_id_1999_1 values less than(to_date('1999-01-01', 'yyyy-mm-dd')),subpartition time_id_2000_1 values less than(maxvalue)) tablespace users) ;

创建分区表指定分区物理属性:

CREATE TABLE test( prod_id NUMBER(6), cust_id NUMBER, time_id DATE, channel_id CHAR(1), promo_id NUMBER(6), quantity_sold NUMBER(3), amount_sold NUMBER(10,2))PARTITION BY list (prod_id)(partition prod_id_1_2 values (1, 2) tablespace users,partition prod_id_3_4 values (3, 4) tablespace users);--添加分区alter table test add partition prod_id_5_6 values (5, 6) pctfree 5;

HASH分区示例:

CREATE TABLE test( prod_id NUMBER(6), cust_id NUMBER)partition by hash (cust_id)partitions 2;select partition_name from user_segments where segment_name = 'TEST';--  SYS_P28--  SYS_P29begin  for x in 1 .. 1000 loop    insert into test values (x, x);  end loop;end;  select a, b from (select count(*) a from test partition (SYS_P28)) test1,(select count(*) b from test partition (SYS_P29)) test2;-- 495 505  --添加HASH分区alter table test add partition SYS_P30;select a, b, c from (select count(*) a from test partition (SYS_P28)) test1,(select count(*) b from test partition (SYS_P29)) test2,(select count(*) c from test partition (SYS_P30)) test3;--  234 505 261--添加HASH分区alter table test add partition SYS_P31;select a, b, c, d from (select count(*) a from test partition (SYS_P28)) test1,(select count(*) b from test partition (SYS_P29)) test2,(select count(*) c from test partition (SYS_P30)) test3,(select count(*) d from test partition (SYS_P31)) test4;--  234 244 261 261

可以看出,对于HASH分区数, ORACLE推荐是2的幂次数,这样有利于数据的平均分布。

分区索引

与分区表类似,分区索引被分解成更小、 更易于管理的索引片断。全局索引独立于它们依赖的表进行分区而局部索引则依据不同的表分区方法,自动链接到相应的表分区。与分区表类似,分区索引提高了可管理性、 可用性、 性能、和可扩展性。

下图显示索引的分区选项。

这里写图片描述

在局部分区索引中,索引基于表上相同的列来分区,与表分区具有相同分区数目和相同的分区边界每个索引分区仅与底层表的一个分区相关联,所以一个索引分区中的所有键都只引用存储在某个单一表分区中的行通过这种方式,数据库会自动同步索引分区及其关联的表分区,使每个表-索引对相持独立

局部分区索引在数据仓库环境中很常见。局部索引提供了以下优点:

 因为使分区中的数据无效或不可用的操作只会影响当前分区,这有助于提高可用性。

 简化了分区维护。当移动一个表分区,或某个分区的数据老化时,只须重建或维持相关联的局部索引分区。而在全局索引中所有索引分区必须被全部重建或维护

如果分区发生时间点恢复,则可以将局部索引恢复到恢复时间 。而不需要重建整个索引

示例 4-4 显示了使用prod_id 列作为分区键的 hash_sales 分区表的创建语句。示例 4-5在hash_sales 表的 time_id列上创建一个局部分区索引。

示例4-5 局部分区索引

CREATE INDEX hash_sales_idx ON hash_sales(time_id) LOCAL;

在图 4-4中, hash_sales 表中有两个分区,因此 hash_sales_idx 也有两个分区。每个索引分区与一个不同的表分区相关联。索引分区 SYS_P38对表分区SYS_P33中的行建立索引,而索引分区 SYS_P39对表分区SYS_P34中的行建立索引。

图 4-4 局部索引分区

这里写图片描述

你不能明确将一个分区添加到一个局部索引中相反,仅当您将一个表分区添加到基础表时,新的索引分区会被自动添加到局部索引同样,不能明确从局部索引删除一个分区。相反,仅当你从基础表中删除一个表分区时,相应的局部索引分区会被自动删除

与其他索引一样,您可以在分区表上创建位图索引。唯一的限制是位图索引必须是局部分区索引 — — 而不能是全局分区索引。全局位图索引只支持非分区表

局部分区索引示例:

--创建分区表create table test (col1 number, col2 number)partition by range (col1)(partition par_10 values less than(50000),partition par_11 values less than(maxvalue));--创建局部分区索引create index ind_test on test(col1) local;--插入测试数据BEGIN  FOR X IN 1 .. 100000 LOOP    INSERT INTO TEST VALUES (X, X);  END LOOP;END;--执行命令,查看执行计划,会使用局部分区索引select * from test partition (par_10) WHERE COL1 = 100;--移动该表分区alert table test move partition par_10;--执行命令,查看执行计划,没有使用局部分区索引select * from test partition (par_10) WHERE COL1 = 100;--此时执行命令,查看另一个分区的执行计划,会使用局部分区索引select * from test partition (par_11) WHERE COL1 = 100;--重建局部索引分区alter index IND_TEST rebuild partition par_10;

局部前缀索引和局部非前缀索引

局部分区索引可分为以下类别:

 局部前缀索引

在这种情况下,分区键处于索引定义的前导部分。示例4-2中, 该表在time_id 上按范围分区。此表上的局部前缀索引会以 time_id作为其索引列列表中的第一列。

 局部非前缀索引

在这种情况下,分区键不是索引列列表的前导部分,甚至根本不必在该列表中。在示例4-5 中,由于分区键 product_id 不属于前导列,所以该索引是局部非前缀索引。

这两种类型的索引都可以充分利用分区消除 (也称为分区剪除) ,此时,优化程序将不予考虑无关分区,以加快数据访问速度查询是否可以消除分区取决于查询谓词。使用局部前缀索引的查询始终允许索引分区消除,而使用一个局部非前缀索引的查询可能不会

局部分区索引存储

与表分区类似,局部索引分区被存储在其自己的段中每个段包含整个索引数据的一部分。因此,由四个分区组成的局部索引,不是存储在一个单一索引段中,而是在四个单独的段中。

全局分区索引

全局分区索引是一个 B-树索引,其分区独立于所依赖的基础表某个索引分区可以指向任意或所有的表分区,而在一个局部分区索引中,索引分区与分区表之间却存在一对一的配对关系。

通常,对于强调快速访问、 数据完整性、和可用性的OLTP 应用程序来说,全局索引很有用。在一个 OLTP 系统中,表可能会基于某个键(如 employees.department_id 列)来分区,但应用程序可能需要基于许多不同的键(如 employee_id 或 job_id)来访问数据。全局索引在这种情况下可能很有用。

你可以按范围或哈希方式建立全局分区索引如果按范围分区,则数据库按你指定的表列的值范围对全局索引进行分区如果按哈希分区,则数据库对分区键列中的值使用哈希函数,并将行分配到相应的分区。

作为演示,假设您在示例 4-2中的time_range_sales 表上创建全局分区索引。在该表中, 1998 年销售的行存储在一个分区中,1999 年销售的行在另一个分区中,如此等等。示例4-6 在 channel_id 列上按范围创建了一个全局分区索引。

示例 4-6 全局分区索引

CREATE INDEX time_channel_sales_idx ON time_range_sales (channel_id)GLOBAL PARTITION BY RANGE (channel_id)(PARTITION p1 VALUES LESS THAN (3),PARTITION p2 VALUES LESS THAN (4),PARTITION p3 VALUES LESS THAN (MAXVALUE));

如图 4-5 ,全局索引分区可以包含指向多个表分区的条目。索引分区p1指向channel_id为2的行,索引分区p2指向channel_id为3的行,而索引分区p3指向channel_id为4或9的行。

图 4-5 全局分区索引

这里写图片描述
这里写图片描述

分区索引组织表

您可以对一个索引组织表 (IOT) 按范围、 列表、或哈希值进行分区。分区有助于改进IOT的可管理性、 可用性、和性能。另外,使用 IOT的数据模块可以利用此功能,对其存储的数据进行分区。

请注意分区 IOT 的以下特征:

 分区列必须是主键列的子集。
 可以对辅助索引进行局部或全局分区。
 溢出数据段总是和表分区一样具有相应的对等分区。

Oracle 数据库支持在分区和未分区索引组织表上的位图索引。在索引组织表上创建位图索引需要一个映射表。

0 0