如何决定Hash Partitions的数目
Kaya 发表于 os2ora.com
Hash也许是计算机科学里的一个重大发明,简单地说,Hash函数实现把一个值映射到相应的buckets里。而Hash函数也在数据仓库领域发挥着举足轻重的作用。
Teradata,一个专注于数据仓库应用的数据库。把并行发挥到极致,它的哲学就在于把任何一个操作都并行化。而并行的基础就在于对数据的Hash分布,通过Hash,实现数据的均匀分布,从而使得并行处理的各个进程能够分担大约相等的任务。
同样地,Oracle也广泛地使用着Hash算法,Hash Partitioning就是在数据仓库应用中的一个典型例子。Hash Partitioning的一个最大的优势就是实现partition wise join.
一个要考虑的问题在于hash partitions数目的选择,一个总的原则是它应该是2的乘方,如4,8,16,32,64,128…
另一个要考虑的方面在于硬件的处理能力,对了,就是RAC里面的节点数,还有每个节点CPU Cores的多少。说得再具体一点,就是默认的DOP的大小(默认DOP = 2 * cpu_count * number of nodes in the cluster)。一般而言,把hash partitions的个数设置成默认的DOP是一个推荐的设置值。在这种问题下,CBO一般会找到最好的执行计划,如利用partition-wise join的特性。
下面的执行计划是一个示例,这是一个利用了parition-wise join的例子。这里,DOP的大小等于hash partitions的个数。
--------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 99999 | 976K| 128 (10)| 00:00:02 | | | | | | | 1 | PX COORDINATOR | | | | | | | | | | | | 2 | PX SEND QC (RANDOM) | :TQ10000 | 99999 | 976K| 128 (10)| 00:00:02 | | | Q1,00 | P->S | QC (RAND) | | 3 | PX PARTITION HASH ALL| | 99999 | 976K| 128 (10)| 00:00:02 | 1 | 4 | Q1,00 | PCWC | | |* 4 | HASH JOIN | | 99999 | 976K| 128 (10)| 00:00:02 | | | Q1,00 | PCWP | | | 5 | TABLE ACCESS FULL | FACT_B | 99999 | 488K| 12 (9)| 00:00:01 | 1 | 4 | Q1,00 | PCWP | | | 6 | TABLE ACCESS FULL | FACT_A | 995K| 4860K| 112 (7)| 00:00:02 | 1 | 4 | Q1,00 | PCWP | | --------------------------------------------------------------------------------------------------------------------------------- Predicate Information (IDENTIFIED BY operation id): --------------------------------------------------- 4 - access("A"."PART_COL1"="B"."PART_COL1")
如果hash partitions的个数比DOP还小,可能会出现下面的执行计划:
------------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib | ------------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 99999 | 976K| 64 (10)| 00:00:01 | | | | | | | 1 | PX COORDINATOR | | | | | | | | | | | | 2 | PX SEND QC (RANDOM) | :TQ10001 | 99999 | 976K| 64 (10)| 00:00:01 | | | Q1,01 | P->S | QC (RAND) | |* 3 | HASH JOIN | | 99999 | 976K| 64 (10)| 00:00:01 | | | Q1,01 | PCWP | | | 4 | PX RECEIVE | | 99999 | 488K| 6 (17)| 00:00:01 | | | Q1,01 | PCWP | | | 5 | PX SEND BROADCAST LOCAL| :TQ10000 | 99999 | 488K| 6 (17)| 00:00:01 | | | Q1,00 | P->P | BCST LOCAL | | 6 | PX BLOCK ITERATOR | | 99999 | 488K| 6 (17)| 00:00:01 | 1 | 4 | Q1,00 | PCWC | | | 7 | TABLE ACCESS FULL | FACT_B | 99999 | 488K| 6 (17)| 00:00:01 | 1 | 4 | Q1,00 | PCWP | | | 8 | PX BLOCK ITERATOR | | 995K| 4860K| 56 (6)| 00:00:01 | 1 | 4 | Q1,01 | PCWC | | | 9 | TABLE ACCESS FULL | FACT_A | 995K| 4860K| 56 (6)| 00:00:01 | 1 | 4 | Q1,01 | PCWP | | ------------------------------------------------------------------------------------------------------------------------------------- Predicate Information (IDENTIFIED BY operation id): --------------------------------------------------- 3 - access("A"."PART_COL1"="B"."PART_COL1")
如果hash partitions的个数比DOP还大,可能会出现下面的执行计划:
-------------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib | -------------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 99999 | 976K| 256 (10)| 00:00:04 | | | | | | | 1 | PX COORDINATOR | | | | | | | | | | | | 2 | PX SEND QC (RANDOM) | :TQ10001 | 99999 | 976K| 256 (10)| 00:00:04 | | | Q1,01 | P->S | QC (RAND) | |* 3 | HASH JOIN | | 99999 | 976K| 256 (10)| 00:00:04 | | | Q1,01 | PCWP | | | 4 | PX BLOCK ITERATOR | | 99999 | 488K| 23 (5)| 00:00:01 | 1 | 4 | Q1,01 | PCWC | | | 5 | TABLE ACCESS FULL | FACT_B | 99999 | 488K| 23 (5)| 00:00:01 | 1 | 4 | Q1,01 | PCWP | | | 6 | BUFFER SORT | | | | | | | | Q1,01 | PCWC | | | 7 | PX RECEIVE | | 995K| 4860K| 224 (6)| 00:00:03 | | | Q1,01 | PCWP | | | 8 | PX SEND BROADCAST LOCAL| :TQ10000 | 995K| 4860K| 224 (6)| 00:00:03 | | | Q1,00 | P->P | BCST LOCAL | | 9 | PX BLOCK ITERATOR | | 995K| 4860K| 224 (6)| 00:00:03 | 1 | 4 | Q1,00 | PCWC | | | 10 | TABLE ACCESS FULL | FACT_A | 995K| 4860K| 224 (6)| 00:00:03 | 1 | 4 | Q1,00 | PCWP | | -------------------------------------------------------------------------------------------------------------------------------------- Predicate Information (IDENTIFIED BY operation id): --------------------------------------------------- 3 - access("A"."PART_COL1"="B"."PART_COL1")
如果hash partitions的个数与默认的DOP一致,那当然可以节省很多时间,如果不是呢,而且要修改Hash Partitions的个数其实不是一件很容易的事情,那就只能通过调整DOP来得到一个好的执行计划了。两种方法:
- 在表一级,通过 alter table parallel <degree>
- 在SQL一级,通过/*+ parallel (table_name, <degree> */

最近评论