在大型的企业应用或企业级的数据库应用中 要处理的数据量通常可以达到几十到几百GB 有的甚至可以到TB级 虽然存储介质和数据处理技术的发展也很快 但是仍然不能满足用户的需求 为了使用户的大量的数据在读写 *** 作和查询中速度更快 Oracle提供了对表和索引进行分区的技术 以改善大型应用系统的性能
使用分区的优点
·增强可用性 如果表的某个分区出现故障 表在其他分区的数据仍然可用
·维护方便 如果表的某个分区出现故障 需要修复数据 只修复该分区即可
·均衡I/O 可以把不同的分区映射到磁盘以平衡I/O 改善整个系统性能
·改善查询性能 对分区对象的查询可以仅搜索自己关心的分区 提高检索速度
Oracle数据库提供对表或索引的分区方法有三种
·范围分区
·Hash分区(散列分区)
·复合分区
下面将以实例的方式分别对这三种分区方法来说明分区表的使用 为了测试方便 我们先建三个表空间
以下为引用的内容
create tablespace dinya_space
datafile /test/demo/oracle/demodata/dinya dnf size M
create tablespace dinya_space
datafile /test/demo/oracle/demodata/dinya dnf size M
create tablespace dinya_space
datafile /test/demo/oracle/demodata/dinya dnf size M
分区表的创建
范围分区
范围分区就是对数据表中的某个值的范围进行分区 根据某个值的范围 决定将该数据存储在哪个分区上 如根据序号分区 根据业务记录的创建日期进行分区等
需求描述 有一个物料交易表 表名 material_transactions 该表将来可能有千万级的数据记录数 要求在建该表的时候使用分区表 这时候我们可以使用序号分区三个区 每个区中预计存储三千万的数据 也可以使用日期分区 如每五年的数据存储在一个分区上
根据交易记录的序号分区建表 以下为引用的内容
SQL>create table dinya_test
(
transaction_id number primary key
item_id number( ) not null
item_description varchar ( )
transaction_date date not null
)
partition by range (transaction_id)
(
partition part_ values less than( ) tablespace dinya_space
partition part_ values less than( ) tablespace dinya_space
partition part_ values less than(maxvalue) tablespace dinya_space
)
Table created
建表成功 根据交易的序号 交易ID在三千万以下的记录将存储在第一个表空间dinya_space 中 分区名为:par_ 在三千万到六千万之间的记录存储在第二个表空间
dinya_space 中 分区名为 par_ 而交易ID在六千万以上的记录存储在第三个表空间dinya_space 中 分区名为par_
根据交易日期分区建表
以下为引用的内容
SQL>create table dinya_test
(
transaction_id number primary key
item_id number( ) not null
item_description varchar ( )
transaction_date date not null
)
partition by range (transaction_date)
(
partition part_ values less than(to_date( yyyy mm dd ))
tablespace dinya_space
partition part_ values less than(to_date( yyyy mm dd ))
tablespace dinya_space
partition part_ values less than(maxvalue) tablespace dinya_space
)
Table created
这样我们就分别建了以交易序号和交易日期来分区的分区表 每次插入数据的时候 系统将根据指定的字段的值来自动将记录存储到制定的分区(表空间)中
当然 我们还可以根据需求 使用两个字段的范围分布来分区 如partition
by range ( transaction_id transaction_date)
分区条件中的值也做相应的改变 请读者自行测试
Hash分区(散列分区)
散列分区为通过指定分区编号来均匀分布数据的一种分区类型 因为通过在I/O设备上进行散列分区 使得这些分区大小一致 如将物料交易表的数据根据交易ID散列地存放在指定的三个表空间中
以下为引用的内容
SQL>create table dinya_test
(
transaction_id number primary key
item_id number( ) not null
item_description varchar ( )
transaction_date date
)
partition by hash(transaction_id)
(
partition part_ tablespace dinya_space
partition part_ tablespace dinya_space
partition part_ tablespace dinya_space
)
Table created
建表成功 此时插入数据 系统将按transaction_id将记录散列地插入三个分区中 这里也就是三个不同的表空间中
复合分区
有时候我们需要根据范围分区后 每个分区内的数据再散列地分布在几个表空间中 这样我们就要使用复合分区 复合分区是先使用范围分区 然后在每个分区内再使用散列分区的一种分区方法 如将物料交易的记录按时间分区 然后每个分区中的数据分三个子分区 将数据散列地存储在三个指定的表空间中
以下为引用的内容
SQL>create table dinya_test
(
transaction_id number primary key
item_id number( ) not null
item_description varchar ( )
transaction_date date
)
partition by range(transaction_date)subpartition by hash(transaction_id)
subpartitions store in (dinya_space dinya_space dinya_space )
(
partition part_ values less than(to_date( yyyy mm dd ))
partition part_ values less than(to_date( yyyy mm dd ))
partition part_ values less than(maxvalue)
)
Table created
该例中 先是根据交易日期进行范围分区 然后根据交易的ID将记录散列地存储在三个表空间中
分区表 *** 作
以上了解了三种分区表的建表方法 下面将使用实际的数据并针对按日期的范围分区来测试分区表的数据记录的 *** 作
插入记录
以下为引用的内容
SQL>insert into dinya_test values( BOOKS sysdate)
row created
SQL>insert into dinya_test values( BOOKS sysdate+ )
row created
SQL>insert into dinya_test values( BOOKS to_date( yyyy mm dd ))
row created
SQL>insert into dinya_test values( BOOKS to_date( yyyy mm dd ))
row created
SQL>insert into dinya_test values( BOOKS to_date( yyyy mm dd ))
row created
SQL>insert into dinya_test values( BOOKS to_date( yyyy mm dd ))
row created
SQL>mit
Commit plete
SQL>
按上面的建表结果 年前的数据将存储在第一个分区part_ 上 而 年到 年的交易数据将存储在第二个分区part_ 上 年以后的记录存储在第三个分区part_ 上
查询分区表记录 以下为引用的内容
SQL>select * from dinya_test partition(part_ )
TRANSACTION_ID ITEM_ID ITEM_DESCRIPTION TRANSACTION_DATE
BOOKS : :
BOOKS : :
SQL>
SQL>select * from dinya_test partition(part_ )
TRANSACTION_ID ITEM_ID ITEM_DESCRIPTION TRANSACTION_DATE
BOOKS
BOOKS
SQL>
SQL>select * from dinya_test partition(part_ )
TRANSACTION_ID ITEM_ID ITEM_DESCRIPTION TRANSACTION_DATE
BOOKS
BOOKS
SQL>
从查询的结果可以看出 插入的数据已经根据交易时间范围存储在不同的分区中 这里是指定了分区的查询 当然也可以不指定分区 直接执行select * from dinya_test查询全部记录
在也检索的数据量很大的时候 指定分区会大大提高检索速度
更新分区表的记录
以下为引用的内容
SQL>update dinya_test partition(part_ ) t set em_description= DESK where
t transaction_id=
row updated
SQL>mit
Commit plete
SQL>
这里将第一个分区中的交易ID= 的记录中的item_description字段更新为 DESK 可以看到已经成功更新了一条记录 但是当更新的时候指定了分区 而根据查询的记录不在该分区中时 将不会更新数据 请看下面的例子 以下为引用的内容
SQL>update dinya_test partition(part_ ) t set em_description= DESK where
t transaction_id=
rows updated
SQL>mit
Commit plete
SQL>
指定了在第一个分区中更新记录 但是条件中限制交易ID为 而查询全表 交易ID为 的记录在第三个分区中 这样该条语句将不会更新记录
删除分区表记录
以下为引用的内容
SQL>delete from dinya_test partition(part_ ) t where t transaction_id=
row deleted
SQL>mit
Commit plete
SQL>
上面例子删除了第二个分区part_ 中的交易记录ID为 的一条记录 和更新数据相同 如果指定了分区 而条件中的数据又不在该分区中时 将不会删除任何数据
分区表索引的使用
分区表和一般表一样可以建立索引 分区表可以创建局部索引和全局索引 当分区中出现许多事务并且要保证所有分区中的数据记录的唯一性时采用全局索引
局部索引分区的建立
以下为引用的内容
SQL>create index dinya_idx_t on dinya_test(item_id)
local
(
partition idx_ tablespace dinya_space
partition idx_ tablespace dinya_space
partition idx_ tablespace dinya_space
)
Index created
SQL>
看查询的执行计划 从下面的执行计划可以看出 系统已经使用了索引
以下为引用的内容
SQL>select * from dinya_test partition(part_ ) t where em_id=
Execution Plan
SELECT STATEMENT Optimizer=CHOOSE (Cost= Card= Bytes= )
TABLE ACCESS (BY LOCAL INDEX ROWID) OF DINYA_TEST (Cost=
Card= Bytes= )
INDEX (RANGE SCAN) OF DINYA_IDX_T (NON UNIQUE) (Cost=
Card= )
Statistics
recursive calls
db block gets
consistent gets
physical reads
redo size
bytes sent via SQL*Net to client
bytes received via SQL*Net from client
SQL*Net roundtrips to/from client
sorts (memory)
sorts (disk)
rows processed
SQL>
全局索引分区的建立
全局索引建立时global 子句允许指定索引的范围值 这个范围值为索引字段的范围值
以下为引用的内容
SQL>create index dinya_idx_t on dinya_test(item_id)
global partition by range(item_id)
(
partition idx_ values less than ( ) tablespace dinya_space
partition idx_ values less than ( ) tablespace dinya_space
partition idx_ values less than (maxvalue) tablespace dinya_space
)
Index created
SQL>
本例中对表的item_id字段建立索引分区 当然也可以不指定索引分区名直接对整个表建立索引 如
以下为引用的内容
SQL>create index dinya_idx_t on dinya_test(item_id)
Index created
SQL>
同样的 对全局索引根据执行计划可以看出索引已经可以使用
以下为引用的内容
SQL>select * from dinya_test t where em_id=
Execution Plan
SELECT STATEMENT Optimizer=CHOOSE (Cost= Card= Bytes= )
TABLE ACCESS (BY GLOBAL INDEX ROWID) OF DINYA_TEST (Cost
= Card= Bytes= )
INDEX (RANGE SCAN) OF DINYA_IDX_T (NON UNIQUE) (Cost=
Card= )
Statistics
recursive calls
db block gets
consistent gets
physical reads
redo size
bytes sent via SQL*Net to client
bytes received via SQL*Net from client
SQL*Net roundtrips to/from client
sorts (memory)
sorts (disk)
rows processed
SQL>
分区表的维护
了解了分区表的建立 索引的建立 表和索引的使用后 在应用的还要经常对分区进行维护和管理 日常维护和管理的内容包括 增加一个分区 合并一个分区及删除分区等等 下面以范围分区为例说明增加 合并 删除分区的一般 *** 作
增加一个分区:
以下为引用的内容
SQL>alter table dinya_test
add partition part_ values less than(to_date( yyyy mm dd ))
tablespace dinya_spa
ce
Table altered
SQL>
增加一个分区的时候 增加的分区的条件必须大于现有分区的最大值 否则系统将提示ORA partition bound must collate higher than that of the last partition 错误
合并一个分区
以下为引用的内容
SQL>alter table dinya_test merge partitions part_ part_ into partition part_
Table altered
SQL>
在本例中将原有的表的part_ 分区和part_ 分区进行了合并 合并后的分区为part_ 如果在合并的时候把合并后的分区定为part_ 的时候 系统将提示ORA cannot reuse lower bound partition as resulting partition 错误
删除分区
以下为引用的内容
SQL>alter table dinya_test drop partition part_
Table altered
SQL>
删除分区表的一个分区后 查询该表的数据时显示 该分区中的数据已全部丢失 所以执行删除分区动作时要慎重 确保先备份数据后再执行 或将分区合并
总结
lishixinzhi/Article/program/Oracle/201311/17329
一 分区表技术概述
二 分区索引技术概述
⑴ 本地前缀分区索引
适用场景:
如果历史数据整理非常频繁、而且不能承受全局分区索引重建的长时间带来的索引不可用
同时、日常交易性能尚能接受、则建议设计为本地非前缀分区索引
注意:本地分区索引不能保证唯一性(除非分区键是约束的一部分)
缺点:
主要体现在数据的高可用性方面
当DROP分区后、全局分区索引则全部INVALID、除非REBULID
但数据量越大、重建索引的时间越长
一般来讲,如果需要将数据按照某个值逻辑聚集,多采用范围分区。如基于时间数据的按“年”、“月”等分区就是很典型的例子。在许多情况下,范围分区都能利用到分区消除特性( = >= <= between…and 等筛选条件下)。
如果在表里无法找到一个合适的属性来按这个属性完成范围分区,但你又想享受分区带来的性能与可用性的提升,则可以考虑使用散列分区。(适合使用 = IN 等筛选条件)
如果数据中有一列或有一组离散值,且按这一列进行分区很有意义,则这样的数据就很适合采用列表分区。
如果某些数据逻辑上可以进行范围分区,但是得到的范围分区还是太大,不能有效管理,则可以考虑使用组合分区(范围分区+hash 或范围分区+列表分区)。
create table products_table
(
id number(2),
name varchar2(50),
sale_date date
)
partition by range(sale_date)
interval (numtoyminterval(1,'month'))
(
partition p_month_1 values less than (to_date('2016-01-01','yyyy-mm-dd'))
)
如图,取 products_table 中的 sale_date 列作为分区键创建按月自增分区;
所有销售时间在 ‘2016-01-01’之前的记录都会被放入 p_month_1 分区;
销售时间在‘2016-01-01’之后的记录在插入时Oracle会自动创建记录所属月的分区;
比如当有销售时间分别为 2016年1月20日 与 2016年2月20日 的两条记录插入时,Oracle会分别创建一个上限值为 ‘2016-01-31’的分区和一个上限值为‘2016-02-29’的分区来存储这两条记录
https://www.cnblogs.com/Dreamer-1/p/6132776.html
Oracle的表分区功能通过改善可管理性、性能和可用性,从而为各式应用程序带来了极大的好处,分区功能能够将表、索引或索引组织表进一步细分为段,这些数据库对象的段叫做分区。
范围分区(RANGE)
范围分区将数据基于范围映射到每一个分区,这个范围是你在创建分区时指定的分区键决定的。这种分区方式是最为常用的,并且分区键经常采用日期。当使用范围分区时,请考虑以下几个规则:
1)每一个分区都必须有一个VALUES LESS THEN子句,它指定了一个不包括在该分区中的上限值。分区键的任何值等于或者大于这个上限值的记录都会被加入到下一个高一些的分区中。
2)所有分区,除了第一个,都会有一个隐式的下限值,这个值就是此分区的前一个分区的上限值。
3)在最高的分区中,MAXVALUE被定义。MAXVALUE代表了一个不确定的值。这个值高于其它分区中的任何分区键的值,也可以理解为高于任何分区中指定的VALUE LESS THEN的值,同时包括空值。
)本地分区索引
本地分区索引是使用了LOCAL属性创建的分区索引,其特征是索引分区的所有键均指向其基表某个 唯一分区中存储的相应行。Oracle创建本地分区索引的目的就是要确保索引也是分区管理的,而且索引的分区与表的分区是均衡的,也就是本地分区索引具有与其基表相同的分区、子分区,即分区键等同于表的分区键、分区数等同于表的分区数。
任何基表分区的增加、删除、合并、分割 *** 作,或者散列分区增加或合并 *** 作,Oracle会通过其自身的机制自动维护本地分区索引相应的分区,此即本地分区索引与基表的均衡性原则。
如果分区列能够形成索引列的一个子集,则本地分区索引可以是唯一索引。该限制能确保具有相同索引键的行始终映射到同一个分区,在该分区中,违反唯一性的行为能被检测到。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)