Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 13 ■ PARTITIONING 589 12 ) 13 / Table created. ops$tkyte@ORA10G> select segment_name, partition_name, segment_type 2 from user_segments; SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE -------------- --------------- ------------------ PARTITIONED PART_1 TABLE PARTITION PARTITIONED PART_2 TABLE PARTITION PARTITIONED_PK INDEX The PARTITIONED_PK index is not even partitioned, let alone locally partitioned, and as we’ll see, it cannot be locally partitioned. Even if we try to trick Oracle by realizing that a primary key can be enforced by a nonunique index as well as a unique index, we’ll find that this approach will not work either: ops$tkyte@ORA10G> CREATE TABLE partitioned 2 ( timestamp date, 3 id int 4 ) 5 PARTITION BY RANGE (timestamp) 6 ( 7 PARTITION part_1 VALUES LESS THAN 8 ( to_date('01-jan-2000','dd-mon-yyyy') ) , 9 PARTITION part_2 VALUES LESS THAN 10 ( to_date('01-jan-2001','dd-mon-yyyy') ) 11 ) 12 / Table created. ops$tkyte@ORA10G> create index partitioned_idx 2 on partitioned(id) local 3 / Index created. ops$tkyte@ORA10G> select segment_name, partition_name, segment_type 2 from user_segments; SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE --------------- --------------- ------------------ PARTITIONED PART_1 TABLE PARTITION PARTITIONED_IDX PART_2 INDEX PARTITION PARTITIONED PART_2 TABLE PARTITION PARTITIONED_IDX PART_1 INDEX PARTITION
590 CHAPTER 13 ■ PARTITIONING ops$tkyte@ORA10G> alter table partitioned 2 add constraint 3 partitioned_pk 4 primary key(id) 5 / alter table partitioned * ERROR at line 1: ORA-01408: such column list already indexed Here, Oracle attempts to create a global index on ID, but finds that it cannot since an index already exists. The preceding statements would work if the index we created was not partitioned, as Oracle would have used that index to enforce the constraint. The reasons why uniqueness cannot be enforced, unless the partition key is part of the constraint, are twofold. First, if Oracle allowed this, it would void most of the advantages of partitions. Availability and scalability would be lost, as each and every partition would always have to be available and scanned to do any inserts and updates. The more partitions you had, the less available the data would be. The more partitions you had, the more index partitions you would have to scan, and the less scalable partitions would become. Instead of providing availability and scalability, doing this would actually decrease both. Additionally, Oracle would have to effectively serialize inserts and updates to this table at the transaction level. This is because if we add ID=1 to PART_1, Oracle would have to somehow prevent anyone else from adding ID=1 to PART_2. The only way to do this would be to prevent others from modifying index partition PART_2, since there isn’t anything to really “lock” in that partition. In an OLTP system, unique constraints must be system enforced (i.e., enforced by Oracle) to ensure the integrity of data. This implies that the logical model of your application will have an impact on the physical design. Uniqueness constraints will either drive the underlying table partitioning scheme, driving the choice of the partition keys, or point you toward the use of global indexes instead. We’ll take a look at global indexes in more depth next. Global Indexes Global indexes are partitioned using a scheme that is different from that used in the underlying table. The table might be partitioned by a TIMESTAMP column into ten partitions, and a global index on that table could be partitioned into five partitions by the REGION column. Unlike local indexes, there is only one class of global index, and that is a prefixed global index. There is no support for a global index whose index key does not begin with the partitioning key for that index. That implies that whatever attribute(s) you use to partition the index will be on the leading edge of the index key itself. Continuing on from our previous example, here is a quick example of the use of a global index. It shows that a global partitioned index can be used to enforce uniqueness for a primary key, so you can have partitioned indexes that enforce uniqueness, but do not include the partition key of TABLE. The following example creates a table partitioned by TIMESTAMP that has an index partitioned by ID:
- Page 584 and 585: CHAPTER 12 ■ DATATYPES 539 ops$tk
- Page 586 and 587: CHAPTER 12 ■ DATATYPES 541 suppor
- Page 588 and 589: CHAPTER 12 ■ DATATYPES 543 Concep
- Page 590 and 591: CHAPTER 12 ■ DATATYPES 545 We can
- Page 592 and 593: CHAPTER 12 ■ DATATYPES 547 buffer
- Page 594 and 595: CHAPTER 12 ■ DATATYPES 549 Note t
- Page 596 and 597: CHAPTER 12 ■ DATATYPES 551 13 dbm
- Page 598 and 599: CHAPTER 12 ■ DATATYPES 553 equall
- Page 600 and 601: CHAPTER 12 ■ DATATYPES 555 ROWID/
- Page 602 and 603: CHAPTER 13 ■ ■ ■ Partitioning
- Page 604 and 605: CHAPTER 13 ■ PARTITIONING 559 6 (
- Page 606 and 607: CHAPTER 13 ■ PARTITIONING 561 els
- Page 608 and 609: CHAPTER 13 ■ PARTITIONING 563 BIG
- Page 610 and 611: CHAPTER 13 ■ PARTITIONING 565 Enh
- Page 612 and 613: CHAPTER 13 ■ PARTITIONING 567 Tab
- Page 614 and 615: CHAPTER 13 ■ PARTITIONING 569 tha
- Page 616 and 617: CHAPTER 13 ■ PARTITIONING 571 PAR
- Page 618 and 619: CHAPTER 13 ■ PARTITIONING 573 35
- Page 620 and 621: CHAPTER 13 ■ PARTITIONING 575 If
- Page 622 and 623: CHAPTER 13 ■ PARTITIONING 577 We
- Page 624 and 625: CHAPTER 13 ■ PARTITIONING 579 14
- Page 626 and 627: CHAPTER 13 ■ PARTITIONING 581 ops
- Page 628 and 629: CHAPTER 13 ■ PARTITIONING 583 In
- Page 630 and 631: CHAPTER 13 ■ PARTITIONING 585 ops
- Page 632 and 633: CHAPTER 13 ■ PARTITIONING 587 | S
- Page 636 and 637: CHAPTER 13 ■ PARTITIONING 591 ops
- Page 638 and 639: CHAPTER 13 ■ PARTITIONING 593 •
- Page 640 and 641: CHAPTER 13 ■ PARTITIONING 595 Now
- Page 642 and 643: CHAPTER 13 ■ PARTITIONING 597 the
- Page 644 and 645: CHAPTER 13 ■ PARTITIONING 599 imp
- Page 646 and 647: CHAPTER 13 ■ PARTITIONING 601 OLT
- Page 648 and 649: CHAPTER 13 ■ PARTITIONING 603 5 s
- Page 650 and 651: CHAPTER 13 ■ PARTITIONING 605 Sur
- Page 652 and 653: CHAPTER 13 ■ PARTITIONING 607 On
- Page 654 and 655: CHAPTER 13 ■ PARTITIONING 609 Row
- Page 656 and 657: CHAPTER 13 ■ PARTITIONING 611 So,
- Page 658 and 659: CHAPTER 13 ■ PARTITIONING 613 Aud
- Page 660 and 661: CHAPTER 14 ■ ■ ■ Parallel Exe
- Page 662 and 663: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 664 and 665: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 666 and 667: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 668 and 669: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 670 and 671: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 672 and 673: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 674 and 675: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 676 and 677: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 678 and 679: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 680 and 681: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 682 and 683: CHAPTER 14 ■ PARALLEL EXECUTION 6
CHAPTER 13 ■ PARTITIONING 589<br />
12 )<br />
13 /<br />
Table created.<br />
ops$tkyte@ORA10G> select segment_name, partition_name, segment_type<br />
2 from user_segments;<br />
SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE<br />
-------------- --------------- ------------------<br />
PARTITIONED PART_1 TABLE PARTITION<br />
PARTITIONED PART_2 TABLE PARTITION<br />
PARTITIONED_PK<br />
INDEX<br />
The PARTITIONED_PK index is not even partitioned, let alone locally partitioned, <strong>and</strong> as<br />
we’ll see, it cannot be locally partitioned. Even if we try to trick <strong>Oracle</strong> by realizing that a primary<br />
key can be enforced by a nonunique index as well as a unique index, we’ll find that this<br />
approach will not work either:<br />
ops$tkyte@ORA10G> CREATE TABLE partitioned<br />
2 ( timestamp date,<br />
3 id int<br />
4 )<br />
5 PARTITION BY RANGE (timestamp)<br />
6 (<br />
7 PARTITION part_1 VALUES LESS THAN<br />
8 ( to_date('01-jan-2000','dd-mon-yyyy') ) ,<br />
9 PARTITION part_2 VALUES LESS THAN<br />
10 ( to_date('01-jan-2001','dd-mon-yyyy') )<br />
11 )<br />
12 /<br />
Table created.<br />
ops$tkyte@ORA10G> create index partitioned_idx<br />
2 on partitioned(id) local<br />
3 /<br />
Index created.<br />
ops$tkyte@ORA10G> select segment_name, partition_name, segment_type<br />
2 from user_segments;<br />
SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE<br />
--------------- --------------- ------------------<br />
PARTITIONED PART_1 TABLE PARTITION<br />
PARTITIONED_IDX PART_2<br />
INDEX PARTITION<br />
PARTITIONED PART_2 TABLE PARTITION<br />
PARTITIONED_IDX PART_1<br />
INDEX PARTITION