Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 10 ■ DATABASE TABLES 407 the setting of 1 would cause dynamic sampling to be used much less often. We can use an ALTER SESSION|SYSTEM command in Oracle9i Release 2 to make it behave the way Oracle 10g does by default, or we can use the dynamic sampling hint as follows: ops$tkyte@ORA9IR2> create global temporary table gtt 2 as 3 select * from scott.emp where 1=0; Table created. ops$tkyte@ORA9IR2> insert into gtt select * from scott.emp; 14 rows created. ops$tkyte@ORA9IR2> set autotrace traceonly explain ops$tkyte@ORA9IR2> select /*+ first_rows */ * from gtt; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=HINT: FIRST_ROWS (Cost=17 Card=8168 Bytes... 1 0 TABLE ACCESS (FULL) OF 'GTT' (Cost=17 Card=8168 Bytes=710616) ops$tkyte@ORA9IR2> select /*+ first_rows dynamic_sampling(gtt 2) */ * from gtt; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=HINT: FIRST_ROWS (Cost=17 Card=14 Bytes=1218) 1 0 TABLE ACCESS (FULL) OF 'GTT' (Cost=17 Card=14 Bytes=1218) ops$tkyte@ORA9IR2> set autotrace off Here, we set the dynamic sampling to level 2 for the table GTT in this query. Left to itself, the optimizer guessed 8,168 rows would be returned from the table GTT. Using dynamic sampling, the estimated cardinality will be much closer to reality (which leads to better query plans overall). Using the level 2 setting, the optimizer quickly scans the table to come up with more-realistic estimates of the true size of this table. In Oracle 10g, we should find this to be less of a problem, because the defaults will cause dynamic sampling to take place: ops$tkyte@ORA10G> create global temporary table gtt 2 as 3 select * from scott.emp where 1=0; Table created. ops$tkyte@ORA10G> insert into gtt select * from scott.emp; 14 rows created. ops$tkyte@ORA10G> set autotrace traceonly explain ops$tkyte@ORA10G> select * from gtt;
408 CHAPTER 10 ■ DATABASE TABLES Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=14 Bytes=1218) 1 0 TABLE ACCESS (FULL) OF 'GTT' (TABLE (TEMP)) (Cost=2 Card=14 Bytes=1218) ops$tkyte@ORA10G> set autotrace off We get the right cardinality without having to ask for it. Dynamic sampling does not come free, however—there is a cost associated with having to perform it at query parse time. If we gathered appropriate representative statistics ahead of time, we could avoid this at hard parse time. That leads us in to DBMS_STATS. There are three methods to use DBMS_STATS to gather representative statistics. The first way is to use DBMS_STATS with the GATHER_SCHEMA_STATS or GATHER_DATABASE_STATS call. These procedures allow you to pass in a parameter, GATHER_TEMP, which is a Boolean and defaults to FALSE. When set to TRUE, any ON COMMIT PRESERVE ROWS global temporary table will have statistics gathered and stored (this technique will not work on ON COMMIT DELETE ROWS tables). Consider the following (note that this was done in an empty schema; the only objects are those you see created): ops$tkyte@ORA10G> create table emp as select * from scott.emp; Table created. ops$tkyte@ORA10G> create global temporary table gtt1 ( x number ) 2 on commit preserve rows; Table created. ops$tkyte@ORA10G> create global temporary table gtt2 ( x number ) 2 on commit delete rows; Table created. ops$tkyte@ORA10G> insert into gtt1 select user_id from all_users; 38 rows created. 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 ); 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 GTT2
- Page 401 and 402: 356 CHAPTER 10 ■ DATABASE TABLES
- 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: 406 CHAPTER 10 ■ DATABASE TABLES
- Page 455 and 456: 410 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
CHAPTER 10 ■ DATABASE TABLES 407<br />
the setting of 1 would cause dynamic sampling to be used much less often. We can use an<br />
ALTER SESSION|SYSTEM comm<strong>and</strong> in <strong>Oracle</strong>9i Release 2 to make it behave the way <strong>Oracle</strong> 10g<br />
does by default, or we can use the dynamic sampling hint as follows:<br />
ops$tkyte@ORA9IR2> create global temporary table gtt<br />
2 as<br />
3 select * from scott.emp where 1=0;<br />
Table created.<br />
ops$tkyte@ORA9IR2> insert into gtt select * from scott.emp;<br />
14 rows created.<br />
ops$tkyte@ORA9IR2> set autotrace traceonly explain<br />
ops$tkyte@ORA9IR2> select /*+ first_rows */ * from gtt;<br />
Execution Plan<br />
----------------------------------------------------------<br />
0 SELECT STATEMENT Optimizer=HINT: FIRST_ROWS (Cost=17 Card=8168 Bytes...<br />
1 0 TABLE ACCESS (FULL) OF 'GTT' (Cost=17 Card=8168 Bytes=710616)<br />
ops$tkyte@ORA9IR2> select /*+ first_rows dynamic_sampling(gtt 2) */ * from gtt;<br />
Execution Plan<br />
----------------------------------------------------------<br />
0 SELECT STATEMENT Optimizer=HINT: FIRST_ROWS (Cost=17 Card=14 Bytes=1218)<br />
1 0 TABLE ACCESS (FULL) OF 'GTT' (Cost=17 Card=14 Bytes=1218)<br />
ops$tkyte@ORA9IR2> set autotrace off<br />
Here, we set the dynamic sampling to level 2 for the table GTT in this query. Left to itself,<br />
the optimizer guessed 8,168 rows would be returned from the table GTT. Using dynamic sampling,<br />
the estimated cardinality will be much closer to reality (which leads to better query<br />
plans overall). Using the level 2 setting, the optimizer quickly scans the table to come up with<br />
more-realistic estimates of the true size of this table. In <strong>Oracle</strong> 10g, we should find this to be<br />
less of a problem, because the defaults will cause dynamic sampling to take place:<br />
ops$tkyte@ORA10G> create global temporary table gtt<br />
2 as<br />
3 select * from scott.emp where 1=0;<br />
Table created.<br />
ops$tkyte@ORA10G> insert into gtt select * from scott.emp;<br />
14 rows created.<br />
ops$tkyte@ORA10G> set autotrace traceonly explain<br />
ops$tkyte@ORA10G> select * from gtt;