I'll show you in my simple example how to slightly improve performance using one of this hints.
For my example I will create "big_table" using Tom Kyte's script as usual.
Creating big_table:
create table big_table as select rownum id, a.* from all_objects a where 1=0 / alter table big_table nologging; declare l_cnt number; l_rows number := 1000000; begin insert /*+ append*/ into big_table select rownum, a.* from all_objects a where rownum <= 1000000; l_cnt := sql%rowcount; commit; while (l_cnt < l_rows) loop insert /*+APPEND */ into big_table select rownum+l_cnt, OWNER,OBJECT_NAME,SUBOBJECT_NAME,OBJECT_ID, DATA_OBJECT_ID,OBJECT_TYPE, CREATED,LAST_DDL_TIME,TIMESTAMP,STATUS,TEMPORARY,GENERATED,SECONDARY,NAMESPACE,EDITION_NAME from big_table where rownum <= l_rows - l_cnt; l_cnt := l_cnt + sql%rowcount; commit; end loop; end; /I will create index on object_id column and gather statistics.
create index i_objectid on big_table(object_id); begin dbms_stats.gather_table_stats ( ownname => user, tabname => 'BIG_TABLE', method_opt => 'for all indexed columns', cascade => TRUE ); end; /It important to mention that Oracle uses index_asc by default so I'll concentrate my example on index_desc hint. Suppose I have a query that scans table for specified range and prints result in descending order.
select * from big_table t where object_id between 30000 and 60000 order by object_id desc;First I will use index_asc hint to gther data. I've flushed buffer for testing purpose.
msutic@TEST11> set timing on msutic@TEST11> set autot traceonly msutic@TEST11> msutic@TEST11> msutic@TEST11> select /*+ index_asc(t i_objectid) */ * from big_table t 2 where object_id between 30000 and 60000 3 order by object_id desc 4 / 429740 rows selected. Elapsed: 00:01:35.59 Execution Plan ---------------------------------------------------------- Plan hash value: 4044193925 --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 431K| 43M| | 441K (1)| 00:26:34 | | 1 | SORT ORDER BY | | 431K| 43M| 60M| 441K (1)| 00:26:34 | | 2 | TABLE ACCESS BY INDEX ROWID| BIG_TABLE | 431K| 43M| | 432K (1)| 00:26:01 | |* 3 | INDEX RANGE SCAN | I_OBJECTID | 431K| | | 972 (2)| 00:00:04 | --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("OBJECT_ID">=30000 AND "OBJECT_ID"<=60000) Statistics ---------------------------------------------------------- 763 recursive calls 11 db block gets 430823 consistent gets 19018 physical reads 0 redo size 5740226 bytes sent via SQL*Net to client 9826 bytes received via SQL*Net from client 861 SQL*Net roundtrips to/from client 10 sorts (memory) 1 sorts (disk) 429740 rows processedIt lasted 1min and 35.59 secs. Notice "SORT ORDER BY" - as resultset was not already sored Oracle used explicit sort to sort output by descending order and that took some time. But what will happen when I use index_desc hint to get resultset sorted in descending order.
msutic@TEST11> select /*+ index_desc(t i_objectid) */ * from big_table t 2 where object_id between 30000 and 60000 3 order by object_id desc 4 / 429740 rows selected. Elapsed: 00:01:12.21 Execution Plan ---------------------------------------------------------- Plan hash value: 2071862395 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 431K| 43M| 432K (1)| 00:26:01 | | 1 | TABLE ACCESS BY INDEX ROWID | BIG_TABLE | 431K| 43M| 432K (1)| 00:26:01 | |* 2 | INDEX RANGE SCAN DESCENDING| I_OBJECTID | 431K| | 972 (2)| 00:00:04 | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("OBJECT_ID">=30000 AND "OBJECT_ID"<=60000) Statistics ---------------------------------------------------------- 707 recursive calls 0 db block gets 431681 consistent gets 11957 physical reads 0 redo size 5740226 bytes sent via SQL*Net to client 9826 bytes received via SQL*Net from client 861 SQL*Net roundtrips to/from client 10 sorts (memory) 0 sorts (disk) 429740 rows processedThis execution lasted 1 min and 12.21 secs whitch is slightly faster then execution before. As you can see, in this example I don't have SORT ORDER BY explicit sort because the resultset was already sorted. Query took advantage of descending index scan to get resultset in descending order. This was just simple example to illustrate how to gain performance benefit using index hints. In many cases it is useless to use this hints but still i made demo case just to try out simple scenario. To clean up:
msutic@TEST11> drop table big_table purge; Table dropped.
0 Comments:
Post a Comment