Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 10 ■ DATABASE TABLES 409 As we can see, only the EMP table was analyzed in this case; the two global temporary tables were ignored. We can change that behavior by calling GATHER_SCHEMA_STATS with GATHER_TEMP => TRUE: ops$tkyte@ORA10G> insert into gtt2 select user_id from all_users; 38 rows created. ops$tkyte@ORA10G> exec dbms_stats.gather_schema_stats( user, gather_temp=>TRUE ); PL/SQL procedure successfully completed. ops$tkyte@ORA10G> select table_name, last_analyzed, num_rows from user_tables; TABLE_NAME LAST_ANAL NUM_ROWS ------------------------------ --------- ---------- EMP 01-MAY-05 14 GTT1 01-MAY-05 38 GTT2 01-MAY-05 0 Notice that the ON COMMIT PRESERVE rows table has accurate statistics, but the ON COMMIT DELETE ROWS does not. DBMS_STATS commits, and that wipes out any information in that table. Do note, however, that GTT2 does now have statistics, which in itself is a bad thing, because the statistics are very much incorrect! It is doubtful the table will have 0 rows in it at runtime. So, if you use this approach, be aware of two things: • Make sure to populate your global temporary tables with representative data in the session that gathers the statistics. If not, they will appear empty to DBMS_STATS. • If you have ON COMMIT DELETE ROWS global temporary tables, this approach should not be used, as you will definitely gather inappropriate values. The second technique that works with ON COMMIT PRESERVE ROWS global temporary tables is to use GATHER_TABLE_STATS directly on the table. You would populate the global temporary table as we just did, and then execute GATHER_TABLE_STATS on that global temporary table. Note that just as before, this does not work for ON COMMIT DELETE ROWS global temporary tables, as the same issues as just described would come into play. The last technique using DBMS_STATS uses a manual process to populate the data dictionary with representative statistics for our temporary tables. For example, if on average the number of rows in the temporary table will be 500, the average row size will be 100 bytes, and the number of blocks will be 7, we could simply use the following: ops$tkyte@ORA10G> create global temporary table t ( x int, y varchar2(100) ); Table created. ops$tkyte@ORA10G> begin 2 dbms_stats.set_table_stats( ownname => USER, 3 tabname => 'T', 4 numrows => 500, 5 numblks => 7, 6 avgrlen => 100 ); 7 end;
410 CHAPTER 10 ■ DATABASE TABLES 8 / PL/SQL procedure successfully completed. ops$tkyte@ORA10G> select table_name, num_rows, blocks, avg_row_len 2 from user_tables 3 where table_name = 'T'; TABLE_NAME NUM_ROWS BLOCKS AVG_ROW_LEN ------------------------------ ---------- ---------- ----------- T 500 7 100 Now, the optimizer won’t use its best guess—it will use our best guess for this information. Temporary Tables Wrap-Up Temporary tables can be useful in an application where you need to temporarily store a set of rows to be processed against other tables, for either a session or a transaction. They are not meant to be used as a means to take a single larger query and “break it up” into smaller result sets that would be combined back together (which seems to be the most popular use of temporary tables in other databases). In fact, you will find in almost all cases that a single query broken up into smaller temporary table queries performs more slowly in Oracle than the single query would have. I’ve seen this behavior time and time again, when given the opportunity to rewrite the series of INSERTs into temporary tables as SELECTs in the form of one large query, the resulting single query executes much faster than the original multistep process. Temporary tables generate a minimum amount of redo, but they still generate some redo, and there is no way to disable that. The redo is generated for the rollback data, and in most typical uses it will be negligible. If you only INSERT and SELECT from temporary tables, the amount of redo generated will not be noticeable. Only if you DELETE or UPDATE a temporary table heavily will you see large amounts of redo generated. Statistics used by the CBO can be generated on a temporary table with care; however, a better guess set of statistics may be set on a temporary table using the DBMS_STATS package or dynamically collected by the optimizer at hard parse time using dynamic sampling. Object Tables We have already seen a partial example of an object table with nested tables. An object table is a table that is created based on a TYPE, not as a collection of columns. Normally, a CREATE TABLE would look like this: create table t ( x int, y date, z varchar2(25) ); An object table creation statement looks more like this: create table t of Some_Type; The attributes (columns) of T are derived from the definition of SOME_TYPE. Let’s quickly look at an example involving a couple of types, and then we’ll review the resulting data structures:
- Page 403 and 404: 358 CHAPTER 10 ■ DATABASE TABLES
- Page 405 and 406: 360 CHAPTER 10 ■ DATABASE TABLES
- Page 407 and 408: 362 CHAPTER 10 ■ DATABASE TABLES
- Page 409 and 410: 364 CHAPTER 10 ■ DATABASE TABLES
- Page 411 and 412: 366 CHAPTER 10 ■ DATABASE TABLES
- Page 413 and 414: 368 CHAPTER 10 ■ DATABASE TABLES
- Page 415 and 416: 370 CHAPTER 10 ■ DATABASE TABLES
- Page 417 and 418: 372 CHAPTER 10 ■ DATABASE TABLES
- Page 419 and 420: 374 CHAPTER 10 ■ DATABASE TABLES
- Page 421 and 422: 376 CHAPTER 10 ■ DATABASE TABLES
- Page 423 and 424: 378 CHAPTER 10 ■ DATABASE TABLES
- Page 425 and 426: 380 CHAPTER 10 ■ DATABASE TABLES
- Page 427 and 428: 382 CHAPTER 10 ■ DATABASE TABLES
- Page 429 and 430: 384 CHAPTER 10 ■ DATABASE TABLES
- Page 431 and 432: 386 CHAPTER 10 ■ DATABASE TABLES
- Page 433 and 434: 388 CHAPTER 10 ■ DATABASE TABLES
- Page 435 and 436: 390 CHAPTER 10 ■ DATABASE TABLES
- Page 437 and 438: 392 CHAPTER 10 ■ DATABASE TABLES
- Page 439 and 440: 394 CHAPTER 10 ■ DATABASE TABLES
- Page 441 and 442: 396 CHAPTER 10 ■ DATABASE TABLES
- Page 443 and 444: 398 CHAPTER 10 ■ DATABASE TABLES
- Page 445 and 446: 400 CHAPTER 10 ■ DATABASE TABLES
- Page 447 and 448: 402 CHAPTER 10 ■ DATABASE TABLES
- Page 449 and 450: 404 CHAPTER 10 ■ DATABASE TABLES
- Page 451 and 452: 406 CHAPTER 10 ■ DATABASE TABLES
- Page 453: 408 CHAPTER 10 ■ DATABASE TABLES
- Page 457 and 458: 412 CHAPTER 10 ■ DATABASE TABLES
- Page 459 and 460: 414 CHAPTER 10 ■ DATABASE TABLES
- Page 461 and 462: 416 CHAPTER 10 ■ DATABASE TABLES
- Page 463 and 464: 418 CHAPTER 10 ■ DATABASE TABLES
- Page 466 and 467: CHAPTER 11 ■ ■ ■ Indexes Inde
- Page 468 and 469: CHAPTER 11 ■ INDEXES 423 value of
- Page 470 and 471: CHAPTER 11 ■ INDEXES 425 One of t
- Page 472 and 473: CHAPTER 11 ■ INDEXES 427 We then
- Page 474 and 475: CHAPTER 11 ■ INDEXES 429 we ended
- Page 476 and 477: CHAPTER 11 ■ INDEXES 431 The data
- Page 478 and 479: CHAPTER 11 ■ INDEXES 433 if ( (++
- Page 480 and 481: CHAPTER 11 ■ INDEXES 435 Table 11
- Page 482 and 483: CHAPTER 11 ■ INDEXES 437 When Sho
- Page 484 and 485: CHAPTER 11 ■ INDEXES 439 an 8KB b
- Page 486 and 487: CHAPTER 11 ■ INDEXES 441 select *
- Page 488 and 489: CHAPTER 11 ■ INDEXES 443 select *
- Page 490 and 491: CHAPTER 11 ■ INDEXES 445 Indicate
- Page 492 and 493: CHAPTER 11 ■ INDEXES 447 an index
- Page 494 and 495: CHAPTER 11 ■ INDEXES 449 Table 11
- Page 496 and 497: CHAPTER 11 ■ INDEXES 451 9 1, 'M'
- Page 498 and 499: CHAPTER 11 ■ INDEXES 453 column w
- Page 500 and 501: CHAPTER 11 ■ INDEXES 455 Bitmap j
- Page 502 and 503: CHAPTER 11 ■ INDEXES 457 INSERT a
410<br />
CHAPTER 10 ■ DATABASE TABLES<br />
8 /<br />
PL/SQL procedure successfully completed.<br />
ops$tkyte@ORA10G> select table_name, num_rows, blocks, avg_row_len<br />
2 from user_tables<br />
3 where table_name = 'T';<br />
TABLE_NAME NUM_ROWS BLOCKS AVG_ROW_LEN<br />
------------------------------ ---------- ---------- -----------<br />
T 500 7 100<br />
Now, the optimizer won’t use its best guess—it will use our best guess for this information.<br />
Temporary Tables Wrap-Up<br />
Temporary tables can be useful in an application where you need to temporarily store a set of<br />
rows to be processed against other tables, for either a session or a transaction. They are not<br />
meant to be used as a means to take a single larger query <strong>and</strong> “break it up” into smaller result<br />
sets that would be combined back together (which seems to be the most popular use of temporary<br />
tables in other databases). In fact, you will find in almost all cases that a single query<br />
broken up into smaller temporary table queries performs more slowly in <strong>Oracle</strong> than the single<br />
query would have. I’ve seen this behavior time <strong>and</strong> time again, when given the opportunity<br />
to rewrite the series of INSERTs into temporary tables as SELECTs in the form of one large query,<br />
the resulting single query executes much faster than the original multistep process.<br />
Temporary tables generate a minimum amount of redo, but they still generate some redo,<br />
<strong>and</strong> there is no way to disable that. The redo is generated for the rollback data, <strong>and</strong> in most<br />
typical uses it will be negligible. If you only INSERT <strong>and</strong> SELECT from temporary tables, the<br />
amount of redo generated will not be noticeable. Only if you DELETE or UPDATE a temporary<br />
table heavily will you see large amounts of redo generated.<br />
Statistics used by the CBO can be generated on a temporary table with care; however, a<br />
better guess set of statistics may be set on a temporary table using the DBMS_STATS package or<br />
dynamically collected by the optimizer at hard parse time using dynamic sampling.<br />
Object Tables<br />
We have already seen a partial example of an object table with nested tables. An object table is<br />
a table that is created based on a TYPE, not as a collection of columns. Normally, a CREATE TABLE<br />
would look like this:<br />
create table t ( x int, y date, z varchar2(25) );<br />
An object table creation statement looks more like this:<br />
create table t of Some_Type;<br />
The attributes (columns) of T are derived from the definition of SOME_TYPE. Let’s quickly<br />
look at an example involving a couple of types, <strong>and</strong> then we’ll review the resulting data<br />
structures: