05.11.2015 Views

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

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

406<br />

CHAPTER 10 ■ DATABASE TABLES<br />

One of the drawbacks of a temporary table in any database is the fact that the optimizer<br />

has no real statistics on it normally. When using the cost-based optimizer (CBO), valid statistics<br />

are vital to the optimizer’s success (or failure). In the absence of statistics, the optimizer will<br />

make guesses as to the distribution of data, the amount of data, <strong>and</strong> the selectivity of an index.<br />

When these guesses are wrong, the query plans generated for queries that make heavy use of<br />

temporary tables could be less than optimal. In many cases, the correct solution is to not use<br />

a temporary table at all, but rather to use an INLINE VIEW (for an example of an INLINE VIEW,<br />

refer to the SELECT just run—it has two of them) in its place. In this fashion, <strong>Oracle</strong> will have<br />

access to all of the relevant statistics for a table <strong>and</strong> can come up with an optimal plan.<br />

I find many times people use temporary tables because they learned in other databases<br />

that joining too many tables in a single query is a “bad thing.” This is a practice that must be<br />

unlearned for <strong>Oracle</strong> development. Rather than trying to outsmart the optimizer <strong>and</strong> breaking<br />

what should be a single query into three or four queries that store their subresults into temporary<br />

tables, <strong>and</strong> then combining the temporary tables, you should just code a single query that<br />

answers the original question. Referencing many tables in a single query is OK; the temporary<br />

table crutch is not needed in <strong>Oracle</strong> for this purpose.<br />

In other cases, however, the use of a temporary table in a process is the correct approach.<br />

For example, I once wrote a Palm sync application to synchronize the date book on a Palm<br />

Pilot with calendar information stored in <strong>Oracle</strong>. The Palm gives me a list of all records that<br />

have been modified since the last hot synchronization. I must take these records <strong>and</strong> compare<br />

them against the live data in the database, update the database records, <strong>and</strong> then generate a<br />

list of changes to be applied to the Palm. This is a perfect example of when a temporary table<br />

is very useful. I used a temporary table to store the changes from the Palm in the database. I<br />

then ran a stored procedure that bumps the Palm-generated changes against the live (<strong>and</strong><br />

very large) permanent tables to discover what changes need to be made to the <strong>Oracle</strong> data,<br />

<strong>and</strong> then to find the changes that need to come from <strong>Oracle</strong> back down to the Palm. I have to<br />

make a couple of passes on this data. First, I find all records that were modified only on the<br />

Palm <strong>and</strong> make the corresponding changes in <strong>Oracle</strong>. Next, I find all records that were modified<br />

on both the Palm <strong>and</strong> my database since the last synchronization <strong>and</strong> rectify them. Then I<br />

find all records that were modified only on the database <strong>and</strong> place their changes into the temporary<br />

table. Lastly, the Palm sync application pulls the changes from the temporary table <strong>and</strong><br />

applies them to the Palm device itself. Upon disconnection, the temporary data goes away.<br />

The issue I encountered, however, is that because the permanent tables were analyzed,<br />

the CBO was being used. The temporary table had no statistics on it (you can analyze the temporary<br />

table, but no statistics are gathered), <strong>and</strong> the CBO would “guess” many things about it.<br />

I, as the developer, knew the average number of rows I might expect, the distribution of the<br />

data, the selectivity of the indexes, <strong>and</strong> so on. I needed a way to inform the optimizer of these<br />

better guesses. There are three ways to give the optimizer statistics on the global temporary<br />

tables. One is via dynamic sampling (new in <strong>Oracle</strong>9i Release 2 <strong>and</strong> above) <strong>and</strong> the other is<br />

the DBMS_STATS package, which has two ways to accomplish this. First, let’s look at dynamic<br />

sampling.<br />

Dynamic sampling is the optimizer’s ability, when hard parsing a query, to scan segments<br />

in the database (sample them) to collect statistics useful in optimizing that particular query.<br />

It is akin to doing a “miniature gather statistics” comm<strong>and</strong> during a hard parse. In <strong>Oracle</strong> 10g,<br />

dynamic sampling will work out of the box, because the default setting has been increased<br />

from 1 to 2, <strong>and</strong> at level 2, the optimizer will dynamically sample any unanalyzed object referenced<br />

in a query processed by the optimizer prior to evaluating the query plan. In 9i Release 2,

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

Saved successfully!

Ooh no, something went wrong!