Showing posts with label ASSOCIATE STATISTICS. Show all posts
Showing posts with label ASSOCIATE STATISTICS. Show all posts

Friday, October 14, 2016

How to associate statistics to a function - Part 2

In our second and last part about association of statistics to PL/SQL functions in Oracle we’ll take a look at how to estimate I/O and CPU usage.

First we’ll try to measure I/O. Let’s have a procedure discount from an online shop. All that it does is that I takes order ID and applies requested discount on it. For I/O measurement we’ll use handy PL/SQL program called mystats which is variation on Jonathan Lewis's SNAP_MY_STATS package to report the resource consumption of a unit of work between two snapshots. You can get it here: https://github.com/oracle-developer/mystats.

Simple example of usage should look like follows:

set serveroutput on
/

begin
 mystats_pkg.ms_start;
end;
/

begin
 discount(1,20);
end;
/

begin
 mystats_pkg.ms_stop(mystats_pkg.statname_ntt('consistent gets','db block gets'));
end;
/

rollback
/


Output will look something like this:



From report we see that our measured I/O is 14. This is very simple and probably not very representative test. It would be a good idea to give procedure more iterations over different data and then divide results by number of iterations.

Now that we now how much I/O will function usually consume, we can focus on CPU.  For CPU estimate we will use PL/SQL function called DBMS_ODCI.ESTIMATE_CPU_UNITS (https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_odci.htm#i996771) which returns the approximate number of CPU instructions (in thousands) corresponding to a specified time interval (in seconds).

We can do something like this with following output:

set serveroutput on
/

declare
 v_start PLS_INTEGER := DBMS_UTILITY.GET_TIME;
 v_end PLS_INTEGER;
begin
 mtg.order_pkg.discount(1,20);
 v_end := DBMS_UTILITY.GET_TIME;
 dbms_output.put_line('Time:'||to_char((v_end-v_start)/100,'999,999.999'));
 DBMS_OUTPUT.PUT_LINE(ROUND(1000 * DBMS_ODCI.ESTIMATE_CPU_UNITS(v_end-v_start)/100,0));
end;
/


rollback
/




Again I would advise you to give it more iterations to get nicer picture a use average value.

Wednesday, August 31, 2016

How to associate statistics to a function - Part 1

It has been a long time since my last post and I’m sorry for that. I’ve been very busy lately and a lot of things happened in my life. Most importantly; I’ve finally decided to move to the next level and I’ve founded my own company – Terama Consulting. You can check our web site here http://www.terama.consulting. We focus mainly on IT consulting, employee training and small cloud services. Feel free to contact us :).

Now, last time we asked ourselves an interesting question. How does Oracle order predicates in where clause and how to tell him how expensive our function really is. Reason for this is that Oracle has none to very limited way to say how CPU or I/O intensive your function is.

We’ll break our post into two parts. In first part, we will learn how to give Oracle information he needs for best possible decision. And second part, where we actually learn how to measure resource consumption, so we know what to tell to Oracle.

So, how to give Oracle information about cost and other attributes of our function?

Answer is quite simple: ASSOCIATE STATISTICS

Purpose of this statement is to associate statistic of given type to our function. By using it, we can tell Oracle what is the CPU cost or our function, what is its selectivity, I/O cost, etc.

Let’s have a look on our options here. We can associate statistics with following object types, while only one set of statistics may be attached to that object:
Columns
Functions
Packages
Types
Indexes
Indextypes

There are certain limitations to what you can set with what object type but I don’t think we need to go into so much detail here. You can study Oracle documentation for that (https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_4006.htm).

Now, let’s see what statistics you can associate with your objects:
CPU cost (number of units greater than 0)
I/O cost (number of units greater than 0)
Network cost (not implemented as of 12c)
Selectivity (number between 0 and 100 where 100 means no filtering at all)

Here are some usage examples:

Selectivity 5%:
ASSOCIATE STATISTICS WITH FUNCTIONS my_where_func DEFAULT SELECTIVITY 5;

CPU cost 950, I/O cost 11 and network cost of 0 (which you can happily ignore):
ASSOCIATE STATISTICS WITH FUNCTIONS my_where_func DEFAULT COST (950,11,0);

All together on one function:
ASSOCIATE STATISTICS WITH FUNCTIONS my_where_func DEFAULT SELECTIVITY 5 DEFAULT COST (950,11,0);

Now it would be a nice time for some execution plans where we play with statistics, but I think you’ve already got the trick. So no execution plans for today and see you in next part :)