Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

rekharaghuram
from rekharaghuram More from this publisher
05.11.2015 Views

CHAPTER 10 ■ DATABASE TABLES 385 the cluster at a time (you have to DROP the existing table in a single table hash cluster before you can create another). Additionally, if there is a one-to-one mapping between hash keys and data rows, the access to the rows is somewhat faster as well. These hash clusters are designed for those occasions when you want to access a table by primary key and do not care to cluster other tables with it. If you need fast access to an employee record by EMPNO, a single table hash cluster might be called for. I did the preceding test on a single table hash cluster as well and found the performance to be even better than just a hash cluster. You could even go a step further with this example, however, and take advantage of the fact that Oracle will allow you to write your own specialized hash function (instead of using the default one provided by Oracle). You are limited to using only the columns available in the table, and you may use only the Oracle built-in functions (e.g., no PL/SQL code) when writing these hash functions. By taking advantage of the fact that OBJECT_ID is a number between 1 and 75,000 in the preceding example, I made my “hash function” simply be the OBJECT_ID column itself. In this fashion, I am guaranteed to never have a hash collision. Putting it all together, I’ll create a single table hash cluster with my own hash function via ops$tkyte@ORA10GR1> create cluster hash_cluster 2 ( hash_key number(10) ) 3 hashkeys 75000 4 size 150 5 single table 6 hash is HASH_KEY 7 / Cluster created. I’ve simply added the key words SINGLE TABLE to make it a single table hash cluster. My HASH IS function is simply the HASH_KEY cluster key in this case. This is a SQL function, so I could have used trunc(mod(hash_key/324+278,555)/abs(hash_key+1)) if I wanted (not that this is a good hash function—it just demonstrates that we can use a complex function there if we wish). I used a NUMBER(10) instead of just a number. Since the hash value must be an integer, it cannot have any fractional components. Then, I create the table in that cluster ops$tkyte@ORA10GR1> create table t_hashed 2 cluster hash_cluster(object_id) 3 as 4 select OWNER, OBJECT_NAME, SUBOBJECT_NAME, 5 cast( OBJECT_ID as number(10) ) object_id, 6 DATA_OBJECT_ID, OBJECT_TYPE, CREATED, 7 LAST_DDL_TIME, TIMESTAMP, STATUS, TEMPORARY, 8 GENERATED, SECONDARY 9 from all_objects 10 / Table created. to build the hashed table. Note the use of the CAST built-in function to make the datatype of OBJECT_ID be what it must be. I ran the test as before (three runs of each block), and this time the runstats output was consistently even more positive:

386 CHAPTER 10 ■ DATABASE TABLES Run1 ran in 224 hsecs Run2 ran in 269 hsecs run 1 ran in 83.27% of the time Name Run1 Run2 Diff STAT...index fetch by key 0 48,178 48,178 STAT...buffer is not pinned co 48,178 96,356 48,178 STAT...table fetch by rowid 0 48,178 48,178 STAT...cluster key scans 48,178 0 -48,178 STAT...session logical reads 48,889 145,245 96,356 STAT...consistent gets 48,184 144,540 96,356 STAT...consistent gets from ca 48,184 144,540 96,356 STAT...consistent gets - exami 48,184 144,540 96,356 LATCH.cache buffers chains 51,663 148,019 96,356 Run1 latches total versus runs -- difference and pct Run1 Run2 Diff Pct 298,987 402,085 103,098 74.36% PL/SQL procedure successfully completed. This single table hash cluster required even less latching into the buffer cache to process (it can stop looking for data sooner, and it has more information). As a result, the TKPROF report shows a measurable decrease in CPU utilization this time around: SELECT * FROM T_HASHED WHERE OBJECT_ID = :B1 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 48178 4.45 4.52 0 2 0 0 Fetch 48178 0.67 0.82 0 48178 0 48178 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 96357 5.12 5.35 0 48180 0 48178 Rows Row Source Operation ------- --------------------------------------------------- 48178 TABLE ACCESS HASH T_HASHED (cr=48178 pr=0 pw=0 time=551123 us) ******************************************************************************** SELECT * FROM T_HEAP WHERE OBJECT_ID = :B1 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 48178 5.38 4.99 0 0 0 0 Fetch 48178 1.25 1.65 0 144534 0 48178 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 96357 6.63 6.65 0 144534 0 48178

CHAPTER 10 ■ DATABASE TABLES 385<br />

the cluster at a time (you have to DROP the existing table in a single table hash cluster before<br />

you can create another). Additionally, if there is a one-to-one mapping between hash keys <strong>and</strong><br />

data rows, the access to the rows is somewhat faster as well. These hash clusters are designed<br />

for those occasions when you want to access a table by primary key <strong>and</strong> do not care to cluster<br />

other tables with it. If you need fast access to an employee record by EMPNO, a single table hash<br />

cluster might be called for. I did the preceding test on a single table hash cluster as well <strong>and</strong><br />

found the performance to be even better than just a hash cluster. You could even go a step further<br />

with this example, however, <strong>and</strong> take advantage of the fact that <strong>Oracle</strong> will allow you to<br />

write your own specialized hash function (instead of using the default one provided by <strong>Oracle</strong>).<br />

You are limited to using only the columns available in the table, <strong>and</strong> you may use only the<br />

<strong>Oracle</strong> built-in functions (e.g., no PL/SQL code) when writing these hash functions. By taking<br />

advantage of the fact that OBJECT_ID is a number between 1 <strong>and</strong> 75,000 in the preceding example,<br />

I made my “hash function” simply be the OBJECT_ID column itself. In this fashion, I am<br />

guaranteed to never have a hash collision. Putting it all together, I’ll create a single table hash<br />

cluster with my own hash function via<br />

ops$tkyte@ORA10GR1> create cluster hash_cluster<br />

2 ( hash_key number(10) )<br />

3 hashkeys 75000<br />

4 size 150<br />

5 single table<br />

6 hash is HASH_KEY<br />

7 /<br />

Cluster created.<br />

I’ve simply added the key words SINGLE TABLE to make it a single table hash cluster. My<br />

HASH IS function is simply the HASH_KEY cluster key in this case. This is a SQL function, so I<br />

could have used trunc(mod(hash_key/324+278,555)/abs(hash_key+1)) if I wanted (not that<br />

this is a good hash function—it just demonstrates that we can use a complex function there if<br />

we wish). I used a NUMBER(10) instead of just a number. Since the hash value must be an integer,<br />

it cannot have any fractional components. Then, I create the table in that cluster<br />

ops$tkyte@ORA10GR1> create table t_hashed<br />

2 cluster hash_cluster(object_id)<br />

3 as<br />

4 select OWNER, OBJECT_NAME, SUBOBJECT_NAME,<br />

5 cast( OBJECT_ID as number(10) ) object_id,<br />

6 DATA_OBJECT_ID, OBJECT_TYPE, CREATED,<br />

7 LAST_DDL_TIME, TIMESTAMP, STATUS, TEMPORARY,<br />

8 GENERATED, SECONDARY<br />

9 from all_objects<br />

10 /<br />

Table created.<br />

to build the hashed table. Note the use of the CAST built-in function to make the datatype of<br />

OBJECT_ID be what it must be. I ran the test as before (three runs of each block), <strong>and</strong> this time<br />

the runstats output was consistently even more positive:

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!