Nested Loop
Nested Loop
Sales Index Unique Primary KeyThis double nested loop means that: for each element of Sales Ticket, scan the unique index of sales. For each element of sales, get the information missing from the index data. This is a classical plan table for a transactional system.
Sales Access by ROWID
Nested LoopThe time needed to perform this join isNested LoopNested LoopNested Loop
The same query using full scan and merge join looks like this
Merge Join
Sort Join
fullscan C
Merge Join
the time needed to perform that join isSort Joinfullscan A
fullscan B
Eventhough your indexes are valid in the context (The number of Good Element is less than 5% of the table), you can see that the more joins you do, the longer the index method takes. Actually one can say that the access time is proportional to power(AccessTableByRowID,NumberOfJoins) which is to be compared to AccessOfFullScan * NumberOfJoin.
Merge Join Cartesian
fullscan AThis is an effect of the Star Query Optimization. Star Query states that if table A and B are small, then it's more efficient to do a direct Cartesian Product (i.e. try all the combinaisons) than to do a regular Join. It's very efficient when the tables are actually small. The time to query such a join is proportional to NumberOfLine(Table A) * NumberOfLine(Table B). The only problem is that Oracle considers a table as small if it fits in the SGA. If you have a big SGA (let's say 500 MO) then any couple of table smaller than 500 MO is candidate to such query optimisation. Actually in alot of cases, you don't want such Star Query.
fullscan B
Nested LoopIndex C1 non unique
Access C by ROWID
... is an example of poor optimization because it forces a full scan for each item found in the index. A nested loop is usually associated with an index. A basic solution is to include hints like:Merge JoinSort JoinFull Scan A
Full Scan B
Select /*+ ORDERED FULL(CC) FULL(AA) FULL(BB) */ ... from A AA, B BB, C CC ....;
which change the execution plan to:
Merge Join
Sort JoinThe ORDERED clause is important. As with indexes, the order of the table to be associated, affects the performance of the join. As a rule of thumb, you should stick to the order of the table given by the use of indexes. Using full scan still requires collecting statistics about the validity of indexes and the historic of column. If an index is better to join two tables (i.e. is the most selective in term of tupples returned), the merge join is going to be a good filter aswell. Remember that the performance of the merge join is linked to the number of tupples returned: the less, the better.Full Scan (C)
Merge JoinSort JoinFull Scan A
Full Scan B
Those files are actually hardlinks to logical raw devices. Logical raw devices are another source of optimization. When Oracle accesses database files, it looks first to see if the block is not in the SGA. The SGA is a very efficient cache system, better than the default Aix File System cache. It's better to use a big SGA which has a consistent size in system memory, than relying only on the Aix Cache system which grows continuously and may swap the SGA out of memory. Using Raw devices allows you to bypass the Aix Cache system. Thats why Raw devices are more efficient standard File System (JFS).
Of course that sort of tuning is a long and tedious activity. You've got to
know the actual size of the table, the degree of parallelism, having plenty
of disk and plenty of memory. If the table increases too quickly you'll
realize that the last slave processes reading the table will work much more
than the others. PQ requires not only to distribute evenly the data between the axes
but to distribute the process time between the processors too.
In the example you can see that the extents of the table are smaller
than the "extent" of the data file. In fact you can have a file "extent" size
slightly smaller than the double of the size of the table extent.
Oracle creates a table extent on a new file when the extent doesnt fit
on the remainder of the previous file.
That allows you to prepare increases in the size of the table.
You can always recreate the table later like this:
drop table foo;
create table foo
...
tablespace tableFooStripped
minextents 16
maxextents 16
size 55Mo;
and be sure that each extent sits on a
different file, i.e. on a different hard disk.
The same way you can do an over stripping if you have big space capacity and alot
of disks like this:
create tablespace tableFooOverStripped
files
'/u08/oradata/SALE/FOO_08.dbf' size 15Mo
'/u09/oradata/SALE/FOO_09.dbf' size 15Mo
'/u10/oradata/SALE/FOO_10.dbf size 15Mo
'/u11/oradata/SALE/FOO_11.dbf size 15Mo
'/u12/oradata/SALE/FOO_12.dbf size 15Mo
'/u13/oradata/SALE/FOO_13.dbf' size 15Mo
'/u14/oradata/SALE/FOO_14.dbf' size 15Mo
'/u15/oradata/SALE/FOO_15.dbf' size 15Mo
'/u15/oradata/SALE/FOO_16.dbf' size 15Mo
'/u17/oradata/SALE/FOO_17.dbf' size 15Mo
'/u18/oradata/SALE/FOO_18.dbf' size 15Mo
'/u19/oradata/SALE/FOO_19.dbf' size 15Mo
'/u20/oradata/SALE/FOO_20.dbf' size 15Mo
'/u21/oradata/SALE/FOO_21.dbf' size 15Mo
'/u22/oradata/SALE/FOO_22.dbf' size 15Mo
'/u23/oradata/SALE/FOO_23.dbf' size 15Mo
'/u24/oradata/SALE/FOO_24.dbf' size 15Mo
default size
min extent 16
max extent 16
size 12Mo...
create table foo
...
tablespace tableFooOverStripped;
Of course you've got to make sure that the different disks are not accessed
at the same time. Parallel Query requires a very big temporary tablespace
and a big rollback segment. You should separate those different tablespaces: