Sunday, 9 May 2010

Oracle Cache Fusion Explained - Part I

A core component of Oracle RAC Database is the Cache Fusion. Cache Fusion should not be intended as a merged buffer cache across all RAC instances. This is what many people thinks and what you may see but the reality is that each node has a private buffer cache and thought Cache Fusion blocks needed by other instances are sent using private interconnect in a complex distributed locking environment.



Cache Fusion Components - PING
Ping is the word used to describe the transfer of a block from instance's buffer cache to another. Process is quite interesting: when an instance needs a block sends a request to the lock master to obtain the desired lock type for that block. If requested block is already locked by other transaction/instance, master will ask to downgrade or release the current lock. This process is called blocking asynchronous trap, or somewhere simple BAST. An instance receiving the BAST usually try to downgrade or release the lock as soon as possibile and to do this many times block has to be flushed to disk. The whole process is called disk ping, or in some books, hard ping. However, from version 10g, when possible, instances try to send the block across private interconnect without write it to disk. Not always this operation is unexpensive. An high transfer of blocks across instances reveal a design problem and impact performances.



Deferred Ping
Deferred Ping is one method used by Oracle to reduce pinging. An instance receiving a BAST may defer to send the block or downgrade its current lock for a maximum of ten milliseconds. This time is used to complete the transaction and write at least block header. Doing this eliminate the need to check the transaction for the receiving instance. Consider that if you read a block header where is marked that a transaction is currently running the instance need to do some checks for example to undo data blocks and this another expensive operation.



Past Image Block (PI)
PI blocks are the copies of blocks recently modified that are sent to another instance due to a BAST. PI blocks are taken by the instance until blocks are flushed to disk by the current owner. When the instance currently owning the blocks write them to disk the Global Cache Services - GCS - tell to the other instances to discard the related PIs. Blocks are written to disk due to checkpoint. If checkpoint is issued from another instance is responsibility to GCS to find the most recent block image to write to disk.



Lock Mastering
Global Cache Services has a memory structure where stores informations about data blocks, this is called lock resource. Every instance tracks its locks and share them also with other instances. As this is a distributed process for each lock exists a Master node. Master node contains information about block, current user, locking request and PIs block. Whenever an instance need a block have to request a data block, it need to contact the master of lock resources. If master is not local, private interconnect will be used to send messages.
Lock combinations available are:














































Lock typeDescription
NL0Null Local and No past Images
SL0Shared Local with no past image
XL0Exclusive Local with no past image
NG0Null Global – Instance owns current block image
SG0Global Shared Lock – Instance owns current image
XG0Global Exclusive Lock – Instance own current image
NG1Global Null – Instance Owns the Past Image Block.
SG1Shared Global – Instance owns past Image
XG1Global Exclusive Lock – Instance owns Past Image.


Remember to query view gv$bh to get block status.

Sunday, 2 May 2010

Does column position affect performance?

Does column position affect performance? The answer is Yes, definitely. Even if many people does not think so or worse they ignore it. Let's explain in few words how Oracle stores row for a table.



For each row you have  a row header that contains usually general information about the data as block address, and type of segments. Also it contains the information about table and the actual row (address) which that holds the data.While Oracle reads each row starting, obviously, from the header and then walking to right till the needed column it's clear that in a table with 300 columns, reading the 300th column is more expensive than reading the 10th. This cost may be computed in about 20 * column_position and as you may think is quite high.


SQL> @demoscriptscreate300col.sql

Table create.

SQL> @demoscriptspopulate300col.sql

SQL> select count(*) from t300col;

  COUNT(*)                                                                                                                                                                                              
----------                                                                                                                                                                                              
     10502                                                                                                                                                                                              

SQL> execute dbms_stats.gather_table_stats(user,'t300col');

PL/SQL procedure successfully completed.

SQL> -- now explain plan for select c1 ... c300 from t300col
SQL> -- then I gather information from plan table.
SQL> -- Costs will be computed for every 10 rows.
SQL> @demoscriptsexp300col.sql

PL/SQL procedure successfully completed.

SQL>SELECT statement_id, cpu_cost AS TOT_CPU_COST, 
 2     cpu_cost-lag(cpu_cost) OVER (ORDER BY statement_id) AS CPU_10ROW_COSTS,
 3     io_cost
 4     FROM plan_table
 5     WHERE id = 0 
 6     ORDER BY statement_id;

STATEMENT_ID                   TOT_CPU_COST   CPU_10ROWS_COSTS   IO_COST                                                                                                                                
------------------------------ -------------- ---------------- ----------                                                                                                                                
1                                   756494187                      23184                                                                                                                                
10                                  758384547         1890360      23184
20                                  760484947         2100400      23184                                                                                                                                                                                                                                                                
30                                  762585347         2100400      23184
40                                  764685747         2100400      23184                                                                                                                                
50                                  766786147         2100400      23184                                                                                                                                
60                                  768886547         2100400      23184                                                                                                                                
70                                  770986947         2100400      23184                                                                                                                                
80                                  773087347         2100400      23184                                                                                                                                
90                                  775187747         2100400      23184 
100                                 777288147         2100400      23184                                                                                                                                
110                                 779388547         2100400      23184                                                                                                                                
120                                 781488947         2100400      23184                                                                                                                                
130                                 783589347         2100400      23184                                                                                                                                
140                                 785689747         2100400      23184                                                                                                                                
150                                 787790147         2100400      23184                                                                                                                                
160                                 789890547         2100400      23184                                                                                                                                
170                                 791990947         2100400      23184                                                                                                                                
180                                 794091347         2100400      23184                                                                                                                                
190                                 796191747         2100400      23184                                                                                                                                
200                                 798292147         2100400      23184                                                                                                                                
210                                 800392547         2100400      23184                                                                                                                                
220                                 802492947         2100400      23184                                                                                                                                
230                                 804593347         2100400      23184                                                                                                                                
240                                 806693747         2100400      23184                                                                                                                                
250                                 808794147         2100400      23184                                                                                                                                
260                                 810894547         2100400      23184                                                                                                                                
270                                 812994947         2100400      23184                                                                                                                                
280                                 815095347         2100400      23184                                                                                                                                
290                                 817195747         2100400      23184                                                                                                                                
300                                 900449897        83254150      23184


So you may see that for each 10 columns there's the same difference in CPU costs and this is quite high. In my example all column were defined as varchar2(255) except for the column 1 that was NUMBER. Now it's clear that this part of database design is very important and may really influence your performances. Many times you can change columns order of a table in online mode using dbms_redefinition but only if your software for each DML and query operation reference any single column. Any star query may not work anymore if columns order is changed.