Search

OakieTags

Who's online

There are currently 0 users and 27 guests online.

Recent comments

Affiliations

March 2011

Things worth to mention and remember (II) - Parallel Execution Control 2

Continuing from the previous installment of this series I'll cover in this post some of the inevitable classics regarding Parallel Execution Control. So forgive me if you're bored by the repetition of known facts - however I still see these things too often used incorrectly, therefore I decided: This is worth to mention and remember!

- Up to and including version 10.2 PARALLEL (without any parameters) and NOLOGGING are valid keywords only in DDL commands

- Applies to all versions: NOLOGGING can not be used as a hint. It can only be specified as part of DDL, for example ALTER INDEX ... REBUILD PARALLEL NOLOGGING.

New York Oracle User Group DBA SIG Webcast

Thank you all those who attended my webcast "Deferred Statistics and SQL Plan Management for Performance in Oracle 11g" for the DBA SIG of New York Oracle User Group. The recording will be available on that website sometime later. In the meantime, here is the zipfile with the slides and the scripts I used for the demo, if you are interested. The script names are referenced in the slides.

Show stuff

There are various “show” commands in SQL*Plus that are convenient short-cuts for simple SQL commands, for example:

show parameter
show recyclebin
show sga
show spparameter

You may find, though, that the output leaves a little to be desired, for example:

show parameter sharing
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
_optimizer_extended_cursor_sharing_r string      SIMPLE
el
cursor_sharing                       string      EXACT

SQL> show parameter dump

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
background_core_dump                 string      partial
background_dump_dest                 string      /u01/app/oracle/diag/rdbms/xxx
                                                 xxx/inst01/trace
core_dump_dest                       string      /u01/app/oracle/diag/rdbms/xxx
                                                 xxx/inst01/cdump
max_dump_file_size                   string      unlimited
shadow_core_dump                     string      PARTIAL
user_dump_dest                       string      /u01/app/oracle/diag/rdbms/xxx
                                                 xxx/inst01/trace

The output can be a little messy because of column limitations – but remember, there is a column command in SQL*Plus to allow you to control the output, and all you’re looking at with the show commands is column output. So try this:

SQL> column name_col_plus_show_param  format a38
SQL> column value_col_plus_show_param format a50
SQL> set linesize 120
SQL> show parameter sharing

NAME                                   TYPE        VALUE
-------------------------------------- ----------- --------------------------------------------------
_optimizer_extended_cursor_sharing_rel string      SIMPLE
cursor_sharing                         string      EXACT
SQL> show parameter dump

NAME                                   TYPE        VALUE
-------------------------------------- ----------- --------------------------------------------------
background_core_dump                   string      partial
background_dump_dest                   string      /u01/app/oracle/diag/rdbms/xxxxxx/inst01/trace
core_dump_dest                         string      /u01/app/oracle/diag/rdbms/xxxxxx/inst01/cdump
max_dump_file_size                     string      unlimited
shadow_core_dump                       string      PARTIAL
user_dump_dest                         string      /u01/app/oracle/diag/rdbms/xxxxxx/inst01/trace

If you issue the column command on its own you get a full listing of all the column definitions and this will show you column formatting options for:

show recyclebin   %_plus_show_recyc
show param        %_col_plus_show_param
show spparam      %_col_plus_show_spparam
show sga          %_name_col_plus_show_sga

autotrace          %_plus_exp  (relevant to pre-10.2 only)

Very Nice...

Recently I wrote about a Chrome plugin that allowed you to block sites from being returned in google search results.

They have gone a step better - they've made that functionality available to anyone logged into google. With any browser! Very nice.

Good Engineering

It's heartbreaking to watch the folks killed, wounded and displaced by the earthquake in the Pacific Ocean. The fury of nature mostly focused on Japan. Surprisingly the damage was not as much as expected in Tokyo. The big city was rattled, nevertheless, but relatively unscathed compared to the lesser known towns and villages. the casualties would have been unthinkably large had the buildings buckled in Tokyo - one of the cities in the world with highest population densities.

How did Tokyo manage to evade the inevitable? Someone twitted - Millions saved in Japan by good engineering and government building code. How profound. Not to belittle the unfathomable suffering of the victims, I couldn't help but think about the parallel to my own profession.

If you Really Can’t Solve a “Simple” Problem..

Sometimes it can be very hard to solve what looks like a simple problem. Here I am going to cover a method that I almost guarantee will help you in such situations.

I recently had a performance issue with an Oracle database that had just gone live. This database is designed to scale to a few billion rows in two key tables, plus some “small” lookup tables of a few dozen to a couple of million rows. Designing a system of this scale with theory only is very dangerous, you need to test at something like the expected volumes. I was lucky, I was on a project where they were willing to put the effort and resource in and we did indeed create a test system with a few billion rows. Data structure and patterns were created to match the expected system, code was tested and we found issues. Root causes were identified, the code was altered and tested, fine work was done. Pleasingly soon the test system worked to SLAs and confidence was high. We had done this all the right way.

We went live. We ramped up the system to a million records. Performance was awful. Eyes swung my way… This was going to be easy, it would be the statistics, the database was 2 days old and I’d warned the client we would need to manage the object statistics. Stats were gathered.
The problem remained. Ohhh dear, that was not expected. Eyes stayed fixed upon me.

I looked at the plan and I quickly spotted what I knew was the problem. The below code is from the test system and line 15 is the key one, it is an index range scan on the primary key, within a nested loop:

   9 |          NESTED LOOPS                       |                           |     1 |   139 |    37   (3)| 00:00:01 |
* 10 |           HASH JOIN SEMI                    |                           |     1 |    50 |    11  (10)| 00:00:01 |
* 11 |            TABLE ACCESS BY INDEX ROWID      | PARTY_ABCDEFGHIJ          |     3 |   144 |     4   (0)| 00:00
* 12 |             INDEX RANGE SCAN                | PA_PK                     |     3 |       |     3   (0)| 00:00:01 |
  13 |            COLLECTION ITERATOR PICKLER FETCH|                           |       |       |            |          |
  14 |           PARTITION RANGE ITERATOR          |                           |    77 |  6853 |    26   (0)| 00:00:01 |
* 15 |            INDEX RANGE SCAN                 | EVEN_PK                   |    77 |  6853 |    26   (0)| 00:00:01 |

On the live system we had an index fast full scan (To be clear, the below is from when I had tried a few things already to fix the problem, but that index_fast_full_scan was the thing I was trying to avoid. Oh and, yes, the index has a different name).

|   9 |          NESTED LOOPS                 |                           |     1 |   125 |  1828   (3)| 00:00:16 |
|  10 |           NESTED LOOPS                |                           |     1 |    63 |     2   (0)| 00:00:01 |
|* 11 |            TABLE ACCESS BY INDEX ROWID| PARTY_ABCDEFGHIJ          |     1 |    45 |     2   (0)| 00:00:01 |
|* 12 |             INDEX UNIQUE SCAN         | PA_PK                     |     1 |       |     1   (0)| 00:00:01 |
|* 13 |            INDEX UNIQUE SCAN          | AGR_PK                    |     1 |    18 |     0   (0)| 00:00:01 |
|  14 |           PARTITION RANGE ITERATOR    |                           |     1 |    62 |  1826   (3)| 00:00:16 |
|* 15 |            INDEX FAST FULL SCAN       | EVE_PK                    |     1 |    62 |  1826   (3)| 00:00:16 |

Now I knew that Oracle would maybe pick that plan if it could get the data it wanted from the index and it felt that the cost was lower than doing multiple range scans. Many reasons could lead to that and I could fix them. This would not take long.

But I could not force the step I wanted. I could not get a set of hints that would force it. I could not get the stats gathered in a way that forced the nested loop range scan. I managed to alter the plan in many ways, fix the order of tables, the types of joins, but kept getting to the point where the access was via the index fast full scan but not by range scan. I thought I had it cracked when I came across a hint I had not known about before, namely the INDEX_RS_ASC {and INDEX_RS_DESC} hint to state do an ascending range scan. Nope, no joy.

By now, 8 hours had passed trying several things and we had a few other people looking at the problem, including Oracle Corp. Oracle Corp came up with a good idea – if the code on test runs fine, copy the stats over. Not as simple as it should be as the test system was not quite as-live but we did that. You guessed, it did not work.

So what now? I knew it was a simple problem but I could not fix it. So I tried a technique I knew had worked before. I’d long passed the point where I was concerned about my pride – I emailed friends and contacts and begged help.

Now, that is not the method of solving problems I am writing about – but it is a damned fine method and I have used it several times. I highly recommend it but only after you have put a lot of effort into doing your own work, if you are willing to give proper details of what you are trying to do – and, utterly crucially, if you are willing to put yourself out and help those you just asked for help on another day.

So, what is the silver bullet method? Well, it is what the person who mailed me back did and which I try to do myself – but struggle with.

Ask yourself, what are the most basic and fundamental things that could be wrong. What is so obvious you completely missed it? You’ve tried complex, you’ve been at this for ages, you are missing something. Sometimes it is that you are on the wrong system or you are changing code that is not the code being executed {I’ve done that a few times over the last 20 years}.

In this case, it was this:

Here is my primary key:

EVEN_PK EABCDE 1 AGR_EXT_SYS_ID
EVEN_PK EABCDE 2 EXT_PRD_HLD_ID_TX
EVEN_PK EABCDE 3 AAAMND_DT
EVEN_PK EABCDE 4 EVT_EXT_SYS_ID
EVEN_PK EABCDE 5 EABCDE_ID

Except, here is what it is on Live

EVE_PK EABCDE 1 EVT_EXT_SYS_ID
EVE_PK EABCDE 2 EABCDE
EVE_PK EABCDE 3 AGR_EXT_SYS_ID
EVE_PK EABCDE 4 EXT_PRD_HLD_ID_TX
EVE_PK EABCDE 5 AAAMND_DT

Ignore the difference in name, that was an artifact of the test environment creation, the key thing is the primary key has a different column order. The DBAs had implemented the table wrong {I’m not blaming them, sometimes stuff just happens OK?}.
Now, it did not alter logical functionality as the Primary Key is on the same columns, but as the access to the table is on only the “leading” three columns of the primary key, if the columns are indexed in the wrong order then Oracle cannot access the index via range scans on those values! Unit testing on the obligatory 6 records had worked fine, but any volume of data revealed the issue.

I could not force my access plan as it was not possible – I had missed the screaming obvious.

So, next time you just “know” you should be able to get your database (or code, or whatever) to do something and it won’t do it, go have a cup of tea, think about your last holiday for 5 minutes and then go back to the desk and ask yourself – did I check that the most fundamental and obvious things are correct.

That is what I think is the key to solving what look like simple problems where you just can’t work it out. Try and think even simpler.

Hotsos 2011 – Mining the AWR Repository for Capacity Planning, Visualization, and other Real World Stuff

For all that loves Oracle performance.. Hotsos is truly the best conference, all the speakers are performance geeks, all the attendees talks about performance. Everything is about performance! There are lot more stuff that I like about my first Hotsos experience, the following are some of them..

I like that presenters and attendees are curious about what each performance geek has to say..

I like that whenever their brains are already fried. They consume as much coffee/soda as they can.. and just lay their butts on this couch.. and still.. talk about performance.

Cursor’s Fury…

Cursor’s Fury is the third book in the Codex Alera series by Jim Butcher. The book starts two years on from where the Academ’s Fury ended.

I can’t even begin to tell you how exciting the last hundred pages of this book were. I was totally freaking out. I finished the last page at about 02:00 in the morning, got out of bed with an exited giggle and ran into the next room to grab the next book in the series. I read that for a couple of hours more before I finally gave up and went to sleep.

If you are thinking about reading this series, please don’t read any spoilers. Jim Butcher has done an brilliant job of mixing predictability and complete surprise. The predictability of the plot works really well because you have a good idea what is going to happen, but you are desperate to see if it does because there are enough surprises to keep you guessing, or questioning what you think is coming round the corner.

Love it.

Tim…

Moats

The (M)other (O)f (A)ll (T)uning (S)cripts. A tuning and diagnostics utility for sqlplus co-developed with Tanel Poder. Includes active session sampling and a TOP-style utility for displaying instance activity at regular refresh intervals. Supports versions from 10g Release 2 onwards. September 2010 (updated March 2011)

Moats

The (M)other (O)f (A)ll (T)uning (S)cripts. A tuning and diagnostics utility for SQL*Plus co-developed with Tanel Poder. Includes active session sampling and a TOP-style utility for displaying instance activity at regular refresh intervals. Supports versions from 10g Release 2 onwards. September 2010 (updated March 2011)