分区有利于管理非常大的表和索引,它使用了一种“分而治之”的逻辑。分区引入了一种分区键(partition key)的概念,分区键用于根据某个区间值(或范围值) 、特定值列表或散列函数值执行数据的聚集。如果让我按某种顺序列出分区的好处,这些好处如下:
(1) 提高数据的可用性:这个特点对任何类型的系统都适用,而不论系统本质上是OLTP还是仓库系统。
(2) 由于从数据库中去除了大段,相应地减轻了管理的负担。在一个100GB的表上执行管理操作时(如重组来删除移植的行,或者在“净化”旧信息后回收表左边的“空白”空间) ,与在各个10GB的表分区上执行10次同样的操作相比,前者负担要大得多。另外,通过使用分区,可以让净化例程根本不留下空白空间,这就完全消除了重组的必要!
(3) 改善某些查询的性能:主要在大型仓库环境中有这个好处,通过使用分区,可以消除很大的数据区间,从而不必考虑它们,相应地根本不用访问这些数据。但这在事务性系统中并不适用,因为这种系统本身就只是访问少量的数据。
(4) 可以把修改分布到多个单独的分区上,从而减少大容量OLTP系统上的竞争:如果一个段遭遇激烈的竞争,可以把它分为多个段,这就可以得到一个副作用:能成比例地减少竞争。
z OLTP系统
在OLTP系统中,不应该把分区当作一种大幅改善查询性能的方法。实际上,在一个传统的OLTP系统中,你必须很小心地应用分区,提防着不要对运行时性能产生负面作用。在传统的OLTP系统中,大多数查询很可能几乎立即返回,而且大多数数据库获取可能都通过一个很小的索引区间扫描来完成。因此,以上所列分区性能方面可能 的主要优点在OLTP系统中表现不出来。 分区消除只在大对象全面扫描时才有用,因为通过分区消除,你可以避免对对象的很大部分做全面扫描。不过,在一个OLTP环 境中,本来就不是对大对象全面扫描(如果真是如此,则说明肯定存在严重的设计缺陷)。即使对索引进行了分区,就算是真的能在速度上有所提高,通过扫描较小 索引所得到的性能提升也是微乎其微的。如果某些查询使用了一个索引,而且它们根本无法消除任何分区,你可能会发现,完成分区之后查询实际上运行得反而更慢 了,因为你现在要扫描5、10或20个更小的索引,而不是一个较大的索引。
z 数据仓库系统
在一个数据仓库/决策支持系统中,分区不仅是一个很强大的管理工具,还可以加快处理的速度。例如,你可能有一个大表,需要在其中执行一个即席查询。你总是按销售定额(sales quarter)执行即席查询,因为每个销售定额包含数十万条记录,而你有数百万条在线记录。因此,你想查询整个数据集中相当小的一部分,但是基于销售定额来索引不太可行。这个索引会指向数十万条记录,以这种方式执行索引区间扫描会很糟糕(有关的更多详细内容请参见第11章)。 处理许多查询时都要求执行一个全表扫描,但是最后却发现,一方面必须扫描数百万条记录,但另一方面其中大多数记录并不适用于我们的查询。如果使用一种明智 的分区机制,就可以按销售定额来聚集数据,这样在查询某个给定销售定额的数据时,就可以只对这个销售定额的数据进行全面扫描。这在所有可能的解决方案中是 最佳的选择。
另外,在一个数据仓库/决策支持环境中,会频繁地使用并行查询。因此,诸如并行索引区间扫描或并行快速全面索引扫描等操作不仅很有意义,而且对我们很有好处。我们希望充分地使用所有可用的资源,并行查询就提供了这样的一种途径。因此,在数据仓库环境中,分区就意味着很有可能会加快处理速度。
表分区机制
目前Oracle中有4种对表分区的方法:
区间分区:可以指定应当存储在一起的数据区间。例如,时间戳在Jan-2005内的所有记录都存储在分区1中,时间戳在Feb-2005内的所有记录都存储在分区2中,依此类推。这可能是Oracle中最常用的分区机制。
散列分区:我们在这一章一个例子中就已经看到了散列分区。这是指在一个(或多个列)上应用一个散列函数,行会按这个散列值放在某个分区中。
列表分区:指定一个离散值集,来确定应当存储在一起的数据。例如,可以指定STATUS列值在(’A’,’M’,’Z’ )中的行放在分区1中,STATUS值在( ‘D’,P’,’Q’ )中的行放在分区2中,依此类推。
组合分区:这是区间分区和散列分区的一种组合,或者是区间分区与列表分区的组合。通过组合分区,你可以先对某些数据应用区间分区,再在区间中根据散列或列表来选择最后的分区。
表分区机制小结
一般来讲,如果将数据按某个(某些)值逻辑聚集,区间分区就很有用。基于时间的数据就是这方面经典的例子,如按“销售定额”、“财政年度”或“月份”分区。在许多情况下,区间分区都能利用分区消除,这包括使用完全相等性和区间(小于、大于、介于…之间等)。
如果不能按自然的区间进行分区,散列分区就很合适。例如,如果必须加载一个表,其中装满与人口普查相关的数据,可能无法找到一个合适的属性来按这个属性完成 区间分区。不过,你可能还是想得到分区提供的管理、性能和可用性提升等诸多好处。在此,只需选择惟一的一个列或几乎惟一的一个列集,对其计算散列。这样一 来,无论有多少个分区,都能得到均匀的数据分布。使用完全相等性或IN(value,value,…)时,散列分区对象可以利用分区消除,但是使用数据区间时,散列分区则无法利用分区消除。
如果数据中有一列有一组离散值,而且根据应用使用这一列的方式来看,按这一列进行分区很有意义(例如,这样一来,查询中可以轻松地利用分区消除),这种数据 就很适合采用列表分区。列表分区的经典例子包括按州或区域代码分区,实际上,一般来讲许多“代码”性属性都很适合应用列表分区。
如果某些数据逻辑上可以进行区间分区,但是得到的区间分区还是太小,不能有效地管理,就可以使用组合分区。可以先应用区间分区,再进一步划分各个区间,按一个散列函数或使用列表来分区。这样就能将I/O请求分布到任何给定大分区中的多个磁盘上。另外,现在可以得到3个层次的分区消除。如果在区间分区键上查询,Oracle就能消除任何不满足条件的区间分区。如果向查询增加散列或列表键,Oracle可以消除该区间中其他的散列或列表分区。如果只是在散列或列表键上查询(而不使用区间分区键), Oracle就只会查询各个区间分区中的这些散列或列表子分区。
我们建议,如果可以按某个属性自然地对数据完成区间分区,就应该使用区间分区,而不是散列分区或列表分区。散列和列表分区能提供分区的许多突出优点,但是在分区消除方面都不如区间分区有用。如果所得到的区间分区太大,不能很好地管理;或者如果你想使用所有PDML功能或对一个区间分区使用并行索引扫描,则建议在区间分区中再使用散列或列表分区。
索引分区
索引与表类似,也可以分区。对索引进行分区有两种可能的方法:
随表对索引完成相应的分区:这也称为局部分区索引(locally pertitioned index) 。每个表分区都有一个索引分区,而且只索引该表分区。一个给定索引分区中的所有条目都指向一个表分区,表分区中的所有行都表示在一个索引分区中。
按区间对索引分区:这也称为全局分区索引(globally partitioned index) 。在此,索引按区间分区(或者在Oracle 10g中该可以按散列分区) ,一个索引分区可能指向任何(和所有)表分区。
(1) 提高数据的可用性:这个特点对任何类型的系统都适用,而不论系统本质上是OLTP还是仓库系统。
(2) 由于从数据库中去除了大段,相应地减轻了管理的负担。在一个100GB的表上执行管理操作时(如重组来删除移植的行,或者在“净化”旧信息后回收表左边的“空白”空间) ,与在各个10GB的表分区上执行10次同样的操作相比,前者负担要大得多。另外,通过使用分区,可以让净化例程根本不留下空白空间,这就完全消除了重组的必要!
(3) 改善某些查询的性能:主要在大型仓库环境中有这个好处,通过使用分区,可以消除很大的数据区间,从而不必考虑它们,相应地根本不用访问这些数据。但这在事务性系统中并不适用,因为这种系统本身就只是访问少量的数据。
(4) 可以把修改分布到多个单独的分区上,从而减少大容量OLTP系统上的竞争:如果一个段遭遇激烈的竞争,可以把它分为多个段,这就可以得到一个副作用:能成比例地减少竞争。
z OLTP系统
在OLTP系统中,不应该把分区当作一种大幅改善查询性能的方法。实际上,在一个传统的OLTP系统中,你必须很小心地应用分区,提防着不要对运行时性能产生负面作用。在传统的OLTP系统中,大多数查询很可能几乎立即返回,而且大多数数据库获取可能都通过一个很小的索引区间扫描来完成。因此,以上所列分区性能方面可能 的主要优点在OLTP系统中表现不出来。 分区消除只在大对象全面扫描时才有用,因为通过分区消除,你可以避免对对象的很大部分做全面扫描。不过,在一个OLTP环 境中,本来就不是对大对象全面扫描(如果真是如此,则说明肯定存在严重的设计缺陷)。即使对索引进行了分区,就算是真的能在速度上有所提高,通过扫描较小 索引所得到的性能提升也是微乎其微的。如果某些查询使用了一个索引,而且它们根本无法消除任何分区,你可能会发现,完成分区之后查询实际上运行得反而更慢 了,因为你现在要扫描5、10或20个更小的索引,而不是一个较大的索引。
z 数据仓库系统
在一个数据仓库/决策支持系统中,分区不仅是一个很强大的管理工具,还可以加快处理的速度。例如,你可能有一个大表,需要在其中执行一个即席查询。你总是按销售定额(sales quarter)执行即席查询,因为每个销售定额包含数十万条记录,而你有数百万条在线记录。因此,你想查询整个数据集中相当小的一部分,但是基于销售定额来索引不太可行。这个索引会指向数十万条记录,以这种方式执行索引区间扫描会很糟糕(有关的更多详细内容请参见第11章)。 处理许多查询时都要求执行一个全表扫描,但是最后却发现,一方面必须扫描数百万条记录,但另一方面其中大多数记录并不适用于我们的查询。如果使用一种明智 的分区机制,就可以按销售定额来聚集数据,这样在查询某个给定销售定额的数据时,就可以只对这个销售定额的数据进行全面扫描。这在所有可能的解决方案中是 最佳的选择。
另外,在一个数据仓库/决策支持环境中,会频繁地使用并行查询。因此,诸如并行索引区间扫描或并行快速全面索引扫描等操作不仅很有意义,而且对我们很有好处。我们希望充分地使用所有可用的资源,并行查询就提供了这样的一种途径。因此,在数据仓库环境中,分区就意味着很有可能会加快处理速度。
表分区机制
目前Oracle中有4种对表分区的方法:
区间分区:可以指定应当存储在一起的数据区间。例如,时间戳在Jan-2005内的所有记录都存储在分区1中,时间戳在Feb-2005内的所有记录都存储在分区2中,依此类推。这可能是Oracle中最常用的分区机制。
散列分区:我们在这一章一个例子中就已经看到了散列分区。这是指在一个(或多个列)上应用一个散列函数,行会按这个散列值放在某个分区中。
列表分区:指定一个离散值集,来确定应当存储在一起的数据。例如,可以指定STATUS列值在(’A’,’M’,’Z’ )中的行放在分区1中,STATUS值在( ‘D’,P’,’Q’ )中的行放在分区2中,依此类推。
组合分区:这是区间分区和散列分区的一种组合,或者是区间分区与列表分区的组合。通过组合分区,你可以先对某些数据应用区间分区,再在区间中根据散列或列表来选择最后的分区。
表分区机制小结
一般来讲,如果将数据按某个(某些)值逻辑聚集,区间分区就很有用。基于时间的数据就是这方面经典的例子,如按“销售定额”、“财政年度”或“月份”分区。在许多情况下,区间分区都能利用分区消除,这包括使用完全相等性和区间(小于、大于、介于…之间等)。
如果不能按自然的区间进行分区,散列分区就很合适。例如,如果必须加载一个表,其中装满与人口普查相关的数据,可能无法找到一个合适的属性来按这个属性完成 区间分区。不过,你可能还是想得到分区提供的管理、性能和可用性提升等诸多好处。在此,只需选择惟一的一个列或几乎惟一的一个列集,对其计算散列。这样一 来,无论有多少个分区,都能得到均匀的数据分布。使用完全相等性或IN(value,value,…)时,散列分区对象可以利用分区消除,但是使用数据区间时,散列分区则无法利用分区消除。
如果数据中有一列有一组离散值,而且根据应用使用这一列的方式来看,按这一列进行分区很有意义(例如,这样一来,查询中可以轻松地利用分区消除),这种数据 就很适合采用列表分区。列表分区的经典例子包括按州或区域代码分区,实际上,一般来讲许多“代码”性属性都很适合应用列表分区。
如果某些数据逻辑上可以进行区间分区,但是得到的区间分区还是太小,不能有效地管理,就可以使用组合分区。可以先应用区间分区,再进一步划分各个区间,按一个散列函数或使用列表来分区。这样就能将I/O请求分布到任何给定大分区中的多个磁盘上。另外,现在可以得到3个层次的分区消除。如果在区间分区键上查询,Oracle就能消除任何不满足条件的区间分区。如果向查询增加散列或列表键,Oracle可以消除该区间中其他的散列或列表分区。如果只是在散列或列表键上查询(而不使用区间分区键), Oracle就只会查询各个区间分区中的这些散列或列表子分区。
我们建议,如果可以按某个属性自然地对数据完成区间分区,就应该使用区间分区,而不是散列分区或列表分区。散列和列表分区能提供分区的许多突出优点,但是在分区消除方面都不如区间分区有用。如果所得到的区间分区太大,不能很好地管理;或者如果你想使用所有PDML功能或对一个区间分区使用并行索引扫描,则建议在区间分区中再使用散列或列表分区。
索引分区
索引与表类似,也可以分区。对索引进行分区有两种可能的方法:
随表对索引完成相应的分区:这也称为局部分区索引(locally pertitioned index) 。每个表分区都有一个索引分区,而且只索引该表分区。一个给定索引分区中的所有条目都指向一个表分区,表分区中的所有行都表示在一个索引分区中。
按区间对索引分区:这也称为全局分区索引(globally partitioned index) 。在此,索引按区间分区(或者在Oracle 10g中该可以按散列分区) ,一个索引分区可能指向任何(和所有)表分区。