Download as pdf or txt
Download as pdf or txt
You are on page 1of 16

Menu

Neil Chandler's DB Blog


A resource for Database Professionals

Advertisements

REPORT THIS AD

Oracle Optimizer System Statistics

System Statistics Are a Little Complex

Oh System statistics! Should we gather them? Should we not?

What do they mean? What are they doing to the optimizer?

[tl;dr – in almost all cases, DON’T GATHER SYSTEM STATISTICS. DON’T SET MBRC. LET
THEM DEFAULT!]
First you need to be armed with a piece of information. When Oracle optimizes your SQL, it
produces a COST to compare each SQL execution plan. Exactly what is this COST? It’s not
seconds. It’s not quite the amount of I/O required. It’s not an arbitrary figure either. Oracle
Optimizer Cost is the cost of getting your data in terms of SINGLE BLOCK READS. Remember this
for later.
Lets have a look at the system stats defaults :

SELECT sname,pname,pval1 FROM SYS.AUX_STATS$ ORDER BY 1,2;


SNAME PNAME PVAL1
-------------------- ------------------------------ ----------
SYSSTATS_INFO DSTART
SYSSTATS_INFO DSTOP
SYSSTATS_INFO FLAGS 0
SYSSTATS_INFO STATUS
SYSSTATS_MAIN CPUSPEED
SYSSTATS_MAIN CPUSPEEDNW 2911 (this will vary)
SYSSTATS_MAIN IOSEEKTIM 10
SYSSTATS_MAIN IOTFRSPEED 4096
SYSSTATS_MAIN MAXTHR
SYSSTATS_MAIN MBRC
SYSSTATS_MAIN MREADTIM
SYSSTATS_MAIN SLAVETHR
SYSSTATS_MAIN SREADTIM
ADVERTISEMENT

REPORT THIS AD

What we are looking for here is the the 3 metrics highlighted in colour. As we can see, the are not
set. By default, we need to calculate those, or know where to find the defaults for those values to
get to them. Once we have those 3 metrics, we can calculate the RATIO used by the optimizer to
convert MULTIBLOCK READ into a cost metric of SINGLE BLOCK READS.

The CPU speed is used to calculate the COST of the query in terms of CPU required. This is small
percentage of the query cost but it may help decide which plan is chosen. This is also converted
from CPU cost into a cost metric of SINGLE BLOCK READS.

Lets get the values for MBRC, MREADTIM and SREADTIM.

MBRC is easy. If it is not explicitly set, it uses the init.ora parameter


“db_file_multiblock_read_count” and uses that. However, by default (and also my
recommendation) this should not be set, meaning Oracle will use the hidden parameter
“_db_file_optimizer_read_count” to cost your queries. This defaults to 8. [note: this is not the
value used in execution. Oracle attempts to do 1MB reads, and uses the value in
“_db_file_exec_read_count” to control the multiblock reads at execution time. For an 8K block
size, this is set to 128.
SREADTIM and MREADTIM are calculations based upon information we now have:
SREADTIM = IOSEEKTIM + db_block_size / IOTFRSPEED = 10+(8192 /4096)
= 12
MREADTIM = IOSEEKTIM + db_block_size * MBRC / IOTFRSPEED =
10+(8192*8/4096) = 26
Right! Now we have more information and can calculate a ratio. The multi block cost-per-block.
This will allow us to take the number of blocks in (for example) a table scan
[DBA_TAB_STATISTICS.BLOCKS statistic] and covert it to the cost metric os SINGLE BLOCK
READS, meaning we can compare (for example) a FULL TABLE SCAN’s I/O directly with the I/O
required for an Index Range Scan and Table Lookup.

multi-block cost-per-block = 1/MBRC * MREADTIM/SREADTIM = 1/8 * 26/12


= 0.270833
If we pull some data from a 10053 trace, where I have a table scan of a table containing
1,000,000 blocks, we should see the 1,000,000 blocks being converted to 270,833 “single block
read blocks” for COST purposes.
[10053] SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for COST_CHECK[COST_CHECK]
SPD: Return code in qosdDSDirSetup: NOCTX, estType = TABLE
Table: COST_CHECK Alias: COST_CHECK
Card: Original: 1000000.000000 Rounded: 1000000 Computed:
1000000.000000 Non Adjusted:1000000.000000
Scan IO Cost (Disk) = 270835.000000
Scan CPU Cost (Disk) = 7411440000.000001
Total Scan IO Cost = 270835.000000 (scan (Disk))
= 270835.000000
Total Scan CPU Cost = 7411440000.000001 (scan (Disk))
= 7411440000.000001
Access Path: TableScan
Cost: 271041.492812 Resp: 271041.492812 Degree: 0
Cost_io: 270835.000000 Cost_cpu: 7411440000
Resp_io: 270835.000000 Resp_cpu: 7411440000
Best:: AccessPath: TableScan
Cost: 271041.492812 Degree: 1 Resp: 271041.492812 Card:
1000000.000000 Bytes: 0.000000
Well we were close! There’s a fudge factor in play here, but 270,835 is pretty

much 270,833
We can also work out the CPU element of the COST.
Scan IO Cost (Disk) = 270835.000000
Cost: 271041.492812
so CPU cost must be 271041.492812 – 270835.000000 = 206.492812

Scan CPU Cost (Disk)=7411440000.000001 so doing the maths to convert to units of “single
block read time”…

CPUSPEEDNW = 2,991 (Mhz, but we convert 2,991,000 Khz)

= 7,411,440,000 / 2,991,000 / SREADTIM


= 2,477.913741223671013039 / 12
= 206.49281176863925108659311267135 cost of CPU in units of SREADTIM
So now you can see how your system statistics can fundamentally change the optimizer by
changing the ratio of multiblock-reads to single block reads.

You want to play yourself and see what happens? Of course you do…
Here’s an excel spreadsheet where you can plug in your numbers and see what happens to the
ratio between single and multi block reads to see how system stats influence the optimizer. By
plugging in different numbers, you will see how complex the interactions are – so what’s the
ideal numbers? Use the DEFAULTS in almost all cases** [WARNING – don’t go changing your
system stats based on this statement. You might experience a significant amount of plan
changes, some of which may be very very bad!]:

[warning – I wrote this is a few mins and it’s not very tested] system_statistics.xlsDownload

Also, this is my version of a script by Franck Pachot, and also based on work by Chris Antognini,
which you can run against your system:

select pname,pval1,calculated,formula from sys.aux_stats$ where sname=’SYSSTATS_MAIN’


model
reference sga on (
select ‘Database Buffers’ name,sum(bytes) value from v$sgastat where name in
(‘shared_io_pool’,’buffer_cache’)
) dimension by (name) measures(value)
reference parameter on (
select name,decode(type,3,to_number(value)) value from v$parameter where
name=’db_file_multiblock_read_count’ and ismodified!=’FALSE’
union all
select name,decode(type,3,to_number(value)) value from v$parameter where name=’sessions’
union all
select name,decode(type,3,to_number(value)) value from v$parameter where
name=’db_block_size’
union all
SELECT a.ksppinm name, to_number(b.ksppstvl) value FROM x$ksppi a, x$ksppsv b WHERE
a.indx=b.indx AND ksppinm like ‘_db_file_optimizer_read_count’
)
dimension by (name) measures(value)
partition by (sname) dimension by (pname) measures (pval1,pval2,cast(null as number) as
calculated,cast(null as varchar2(120)) as formula) rules(
calculated[‘MBRC’]=coalesce(pval1[‘MBRC’],parameter.value[‘db_file_multiblock_read_count’],pa
rameter.value[‘_db_file_optimizer_read_count’],8),
calculated[‘MREADTIM’]=coalesce(pval1[‘MREADTIM’],pval1[‘IOSEEKTIM’] +
(parameter.value[‘db_block_size’] * calculated[‘MBRC’] ) / pval1[‘IOTFRSPEED’]),
calculated[‘SREADTIM’]=coalesce(pval1[‘SREADTIM’],pval1[‘IOSEEKTIM’] +
parameter.value[‘db_block_size’] / pval1[‘IOTFRSPEED’]),
calculated[‘_multi block Cost per
block’]=round(1/calculated[‘MBRC’]*calculated[‘MREADTIM’]/calculated[‘SREADTIM’],4),
calculated[‘_single block Cost per block’]=1,
formula[‘MBRC’]=case when pval1[‘MBRC’] is not null then ‘MBRC’ when
parameter.value[‘db_file_multiblock_read_count’] is not null then ‘db_file_multiblock_read_count’
when parameter.value[‘_db_file_optimizer_read_count’] is not null then
‘_db_file_optimizer_read_count (db_file_multiblock_read_count not set, which is good!)’ else ‘=
not sure so used 8’ end,
formula[‘MREADTIM’]=case when pval1[‘MREADTIM’] is null then ‘= IOSEEKTIM +
db_block_size * MBRC / IOTFRSPEED’ end||’ =
‘||pval1[‘IOSEEKTIM’]||’+(‘||parameter.value[‘db_block_size’]||’*’||calculated[‘MBRC’]||’/’||pval1[
‘IOTFRSPEED’]||’)’,
formula[‘SREADTIM’]=case when pval1[‘SREADTIM’] is null then ‘= IOSEEKTIM + db_block_size
/ IOTFRSPEED’ end||’ =
‘||pval1[‘IOSEEKTIM’]||’+(‘||parameter.value[‘db_block_size’]||’/’||pval1[‘IOTFRSPEED’]||’)’,
formula[‘_multi block Cost per block’]=’= 1/MBRC * MREADTIM/SREADTIM =
1/’||calculated[‘MBRC’]||’ * ‘||calculated[‘MREADTIM’]||’/’||calculated[‘SREADTIM’],
calculated[‘_maximum mbrc’]=sga.value[‘Database
Buffers’]/(parameter.value[‘db_block_size’]*parameter.value[‘sessions’]),
formula[‘_maximum mbrc’]=’= buffer cache blocks/sessions (small cache limiter) = ‘ ||
sga.value[‘Database Buffers’]/parameter.value[‘db_block_size’]||’/’||parameter.value[‘sessions’],
formula[‘_single block Cost per block’]=’relative to the multi blovk cost per block. Always 1!’,
formula[‘CPUSPEED’]=’overrides CPUSPEEDNW when set’,
formula[‘CPUSPEEDNW’]=’CPU speed Mhz – non workload’,
formula[‘IOSEEKTIM’]=’IO seek time in ms’,
formula[‘IOTFRSPEED’]=’IO transfer speed in KB/s’,
formula[‘MAXTHR’]=’Maximum IO system throughput’,
formula[‘SLAVETHR’]=’average parallel slave IO throughput’
) order by 1;
** there is a case for gathering ‘exadata’ system stats. Increasing the IOTRFSPEED to 200,000
and changing the MBRC to (probably) 128 or 64 will *really* change the ratios, forcing a lot of
full table scans down onto the storage cells, instead of using mediocre indexes. This should be
considered (and thoroughly tested) if you have a DW on a dedicated Exadata.
3rd February 2021Leave a Reply

Goldengate Install Error


Sometimes you waste much more time than you can believe because the instrumentation of the
system isn’t great. If you don’t know what a system is doing, you can’t easily fix it. Time should
be take to instrument your code, and ensure that any outputs from that instrumentation are
readily understandable by others.

Here’s a mild frustration from this week that I encountered. I was installing Goldengate…

./runInstaller -silent -waitforcompletion -responseFile


/u01/migrate/gg/software/fbo_ggs_Linux_x64_shiphome/Disk1/install_source.rs
p

Starting Oracle Universal Installer...

Checking Temp space: must be greater than 120 MB. Actual 21571 MB Passed

Checking swap space: must be greater than 150 MB. Actual 24575 MB Passed

Preparing to launch Oracle Universal Installer from /tmp/OraInstall2020-07-


30_08-03-36PM. Please wait ...

[WARNING] [INS-08109] Unexpected error occurred while validating inputs at


state 'installOptions'.

CAUSE: No additional information available.

ACTION: Contact Oracle Support Services or refer to the software manual.


SUMMARY:
- java.lang.NullPointerException
Oh my word! ACTION: Contact Oracle Support Services! java.lang.NullPointerException!
Something is terribly wrong!

I’d better re-read this error message carefully… Unexpected error occurred while validating
inputs at state ‘installOptions’. What? Validating inputs? Lets have a look at the inputs from the
response file:
install_source.rsp

###########################################################################
#####
## ##

## Oracle GoldenGate installation option and details ##

## ##

###########################################################################
#####

#--------------------------------------------------------------------------
-----

# Specify the installation option.

# Specify ORA19c for installing Oracle GoldenGate for Oracle Database 19c
or

# ORA18c for installing Oracle GoldenGate for Oracle Database 18c or

# ORA12c for installing Oracle GoldenGate for Oracle Database 12c or

# ORA11g for installing Oracle GoldenGate for Oracle Database 11g

#--------------------------------------------------------------------------
-----

INSTALL_OPTION=ORA11G

#--------------------------------------------------------------------------
-----

# Specify a location to install Oracle GoldenGate

#--------------------------------------------------------------------------
-----

SOFTWARE_LOCATION=/u01/gg
START_MANAGER=

MANAGER_PORT=

DATABASE_LOCATION=

INVENTORY_LOCATION=

UNIX_GROUP_NAME=

I only have 2 inputs; the INSTALL_OPTION and the SOFTWARE_LOCATION… and the
INSTALL_OPTION is wrong! This field is case sensitive. ORA11G does not match ORA11g, so I get
a dramatic null pointer exception and a failure. It would have been a much quicker remediation
if the Oracle error had been curated a little better and the programmer a little more sympathetic
to users of their code.
How about:
Installation parameter INSTALL_OPTION invalid,
rather than
Unexpected error occurred while validating inputs at state ‘installOptions’

31st July 2020Leave a Reply

Oracle Database GLOBAL_NAME, DB_DOMAIN and database links


I needed to create a database link on a 19.7C Oracle DB recently. Importantly, the database link
name must match the database name as security dictates that GLOBAL_NAMES=TRUE for this
set of databases. The DB was created using the gui on an ODA, meaning there were quite a few
initialisation parameters set by the gui.

Lets see what happened and what I had to do to actually get a database link with the same name
as the database.

> create database link ORA11A connect to neil identified by neil using
'ORA11A';

Database link created.

> select owner,db_link,username,host from dba_db_links;

OWNER DB_LINK USERNAME HOST


----- ----------------------- ------------ ------------

SYS ORA11A.CHANDLER.UK.COM NEIL ORA11A

> drop database link ORA11A;


What? Why was a domain being appended to the database link name?

> select name,value,description from v$parameter where name = 'db_domain';

NAME VALUE DESCRIPTION

---------- ---------------- -----------------------------------------------


---------------------------------

db_domain chandler.uk.com directory part of global database name stored


with CREATE DATABASE

> alter system reset db_domain scope=spfile sid='*';

(restart db)

> select name,value,description from v$parameter where name = 'db_domain';

NAME VALUE DESCRIPTION

---------- ---------------- -----------------------------------------------


---------------------------------

db_domain directory part of global database name stored


with CREATE DATABASE

> create database link ORA11A connect to neil identified by neil using
'ORA11A';

> select owner,db_link,username,host from dba_db_links;


OWNER DB_LINK USERNAME HOST

----- ----------------------- ------------ ------------

SYS ORA11A.CHANDLER.UK.COM NEIL ORA11A


So it’s not coming from the DB_DOMAIN! But there’s a clue in the description “directory part of
global database name stored with CREATE DATABASE“. Lets check the global name:
select * from global_name;

GLOBAL_NAME

------------------------------

ORA19A.CHANDLER.UK.COM

So maybe it’s taking the domain from here? Can I prove that?

>alter database rename global_name to "ORA19A.COM";

Database altered.

> select * from global_name;

GLOBAL_NAME

------------------------------

ORA19A.COM

> create database link ORA11A connect to neil identified by neil using
'ORA11A';

Database link created.

> select owner,db_link,username,host from dba_db_links;


OWNER DB_LINK USERNAME HOST

----- ----------------------- ------------ ------------

SYS ORA11A.CHANDLER.UK.COM NEIL ORA11A

SYS ORA11A.COM NEIL ORA11A

[note that I had not deleted the previous DB link so it was still there!]

So, all I needs to do now is remove the “.COM”

> alter database rename global_name to "ORA19A";

Database altered.

> select * from global_name;

GLOBAL_NAME

------------------------------

ORA19A.COM

Oh dear. You can’t remove a domain suffix from a global name. If you don’t specify the
domain, Oracle helpfully adds it right back in there for you.
You need to correct this in an unorthodox way.
The GLOBAL_NAME is really a value in SYS.PROPS$

> select text from dba_views where view_name = 'GLOBAL_NAME';

TEXT

-----------------------------------------------------------

select value$ from sys.props$ where name = 'GLOBAL_DB_NAME'

So we will have to update the value in SYS.PROPS$ directly.


THIS IS NOT A SUPPORTED ACTION.
DON’T DO IT WITHOUT A CONVERSATION WITH ORACLE SUPPORT.
[Check MOS note: 1018063.102]
***updating sys.props$ incorrectly can corrupt your entire database ***

> select value$,comment$ from sys.props$ where name = 'GLOBAL_DB_NAME';

VALUE$ COMMENT$

------------------------------ --------------------------------------------
------------------------------------

ORA19A.COM Global database name

> update sys.props$ set value$='ORA19A' where name = 'GLOBAL_DB_NAME';

1 row updated.

> commit;

Commit complete.

select value$,comment$ from sys.props$ where name = 'GLOBAL_DB_NAME';

VALUE$ COMMENT$

------------------------------ --------------------------------------------
------------------------------------

ORA19A Global database name

> create database link ORA11A connect to neil identified by neil using
'ORA11A';
Database link created.

> select owner,db_link,username,host from dba_db_links;

OWNER DB_LINK USERNAME HOST

----- ----------------------- ------------ ------------

SYS ORA11A.CHANDLER.UK.COM NEIL ORA11A

SYS ORA11A.COM NEIL ORA11A

SYS ORA11A NEIL ORA11A


Finally I can use the DB_LINK with GLOBAL_NAME=TRUE!

If only I’d created the database without specifying a db_domain in the first place…

20th July 2020Leave a Reply

UKOUG Techfest19
I’ve just returned from Techfest19 – the UKOUG Flagship Oracle Tech conference – and it was
simply excellent.

Amazing Sunset from the Grand

It was held at The Grand Hotel in Brighton, and it was grand. If you missed it, you really missed
out. 250 mostly amazing presentations.
I did 2 main ones about Oracle Statistics, and also MC’d the Jonathan Lewis Optimizer Panel,
alongside Martin Widlake. The highlight of my conference was asking a left-field question of an
Oracle Architect about Full Table Scans, which has resulted in the potential for a change to the
code to make them (possibly slightly) more efficient. Thank you for listening Roger!

Oracle ACE Dinner

If you missed my 2 sessions on Database Statistics, you can find a webinar and a Blair-Witch
style video of each of them here on my website:

▪ Oracle Database Statistics – The Easy Way


▪ Oracle Database Statistics – When It’s Harder

UKOUG Guest Speaker, before the party

5th December 2019


Oracle Tech Conferences
It’s mid-November 2019. The leaves have mostly fallen and the nights are drawing in. That can
only mean… it’s time for Europes 2 biggest Independent Oracle User Groups to have their
conferences.

The first, starting Tuesday 18th November, is DOAG – the German Oracle User Group – in Nuremberg.

I’m flying out there a couple of days beforehand as I have


meetings, and it’s nice to travel and chill out too. This year I’m speaking about Oracle Database Statistics at
both conferences, but I only have time for the “basics” talk at DOAG so I’ll try to get some Unconference
time to talk about when it gets harder.
Then, from the 1st to the 4th December, it’s the UKOUG Techfest 2019. This is slightly different
this year as we have split the main conference, comprising Tech, Business Apps and JDE into 3
separate components at different times of the year. The Tech-only conference has stayed in the
December slot (with Business Apps moving to June).
We have also moved the conference to Brighton. New location, Great town.

I’ll be talking about Oracle Database Statistics, but this time in 2 slots, Database Stats #1. Doing
it Right, the Easy Way (Monday 2nd December 09:00), then in a bit more depth I’ll do Database
Stats #2. Doing it Right, When it’s Harder (Wednesday 4th December 11:00)
For a UKOUG “conference survival guide”, I recommend

UKOUG Techfest
Survival Guide 2019. All you need to know about getting the most out of 3.5 days of Tech shenanigans.
Turn up, learn, but also try to meet people and have fun! I hope to see you at one of both of these
conferences, maybe have a coffee or somethings stronger – easy on the stalking though (read Martins
Survival Guide first)
If you have not registered for Techfest 2019, you can do that here: UKOUG TechFest 2019!
There a full agenda of around 250 Oracle-related Tech talks. The problem isn’t trying to work
out if there’s enough to see, but trying to work out how to prioritise all of them!
See you there!

16th November 2019Leave a Reply

Older posts

Categories
Categories Select
Category ACFS Administration Appearances audit Backups DataGuard Datapump Development doag Goldengate
GRID Infrastructure HrOUG Ireland Management Migration oracle patching Performance and
Tuning POUG Prevarication Problem
Solving Programming RAC Recruitment rigadevdays RMAN SAN SCHEMA Security sig SIOUG spm SpOUG SQL
UKOUG Uncategorized Unix User Groups
Archives
Archives Select Month February 2021 July 2020 December 2019 November 2019 September 2019 March
2019 February 2019 January 2019 November 2018 October 2018 September 2018 August 2018 June
2018 May 2018 April 2018 March 2018 February 2018 January 2018 December 2017 November
2017 September 2017 August 2017 May 2017 March 2017 February 2017 January 2017 December
2016 November 2016 October 2016 September 2016 July 2016 May 2016 April 2016 March
2016 February 2016 January 2016 November 2015 October 2015 September 2015 August 2015 July
2015 June 2015 May 2015 April 2015 March 2015 February 2015 January 2015 December
2014 November 2014 October 2014 September 2014 June 2014 May 2014 April 2014 March
2014 December 2013 November 2013 October 2013 September 2013 August 2013 July 2013 May
2013 February 2013 January 2013 September 2012 August 2012 July 2012 June 2012 May 2012 April
2012 March 2012 February 2012 January 2012 December 2011 November 2011 October 2011 September
2011 July 2011 May 2011 March 2011

MyWebsite
• Neil Chandler
My Tweets

Meta
• Register
• Log in
• Entries feed
• Comments feed
• WordPress.com

View Full Site

You might also like