A New Version of an Old Trick

A long, long time ago, people started using the following SQL idiom:

with t as (select /*+ materialize */ …..)

select …. from t

If my memory serves me right, Jonathan Lewis was the first person whom I saw using this idiom. The use of that idiom was to speed create a global temporary table and reuse the query results, without having to re-execute query again. Here is an example:

SQL> set autotrace on

SQL> set timing on

SQL> with t as (select /*+ materialize */ * from dba_objects)

2 select count(*) from t;

COUNT(*)

———-

87661

Elapsed: 00:00:02.67

Execution Plan

———————————————————-

Plan hash value: 3274171655

——————————————————————————–

——————————

| Id | Operation | Name | Rows | B

ytes | Cost (%CPU)| Time |

——————————————————————————–

——————————

| 0 | SELECT STATEMENT | | 1 |

| 570 (15)| 00:00:01 |

| 1 | TEMP TABLE TRANSFORMATION | | |

| | |

| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D6608_4A7EB2 | |

| | |

| 3 | VIEW | DBA_OBJECTS | 87374 |

13M| 239 (24)| 00:00:01 |

| 4 | UNION-ALL | | |

| | |

|* 5 | TABLE ACCESS BY INDEX ROWID | SUM$ | 1 |

9 | 1 (0)| 00:00:01 |

|* 6 | INDEX UNIQUE SCAN | I_SUM$_1 | 1 |

| 0 (0)| 00:00:01 |

| 7 | TABLE ACCESS BY INDEX ROWID | OBJ$ | 1 |

30 | 3 (0)| 00:00:01 |

|* 8 | INDEX RANGE SCAN | I_OBJ1 | 1 |

| 2 (0)| 00:00:01 |

|* 9 | FILTER | | |

| | |

|* 10 | HASH JOIN | | 87373 |

10M| 237 (24)| 00:00:01 |

| 11 | TABLE ACCESS FULL | USER$ | 99 |

1683 | 2 (0)| 00:00:01 |

|* 12 | HASH JOIN | | 87373 |

9044K| 230 (23)| 00:00:01 |

| 13 | INDEX FULL SCAN | I_USER2 | 99 |

2178 | 1 (0)| 00:00:01 |

|* 14 | TABLE ACCESS FULL | OBJ$ | 87373 |

7167K| 224 (21)| 00:00:01 |

| 15 | NESTED LOOPS | | 1 |

29 | 2 (0)| 00:00:01 |

|* 16 | INDEX SKIP SCAN | I_USER2 | 1 |

20 | 1 (0)| 00:00:01 |

|* 17 | INDEX RANGE SCAN | I_OBJ4 | 1 |

9 | 1 (0)| 00:00:01 |

| 18 | NESTED LOOPS | | 1 |

105 | 2 (0)| 00:00:01 |

| 19 | NESTED LOOPS | | 99 |

105 | 2 (0)| 00:00:01 |

| 20 | TABLE ACCESS FULL | USER$ | 99 |

1683 | 2 (0)| 00:00:01 |

|* 21 | INDEX RANGE SCAN | I_LINK1 | 1 |

| 0 (0)| 00:00:01 |

| 22 | TABLE ACCESS BY INDEX ROWID| LINK$ | 1 |

88 | 0 (0)| 00:00:01 |

| 23 | SORT AGGREGATE | | 1 |

| | |

| 24 | VIEW | | 87374 |

| 331 (8)| 00:00:01 |

| 25 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6608_4A7EB2 | 87374 |

13M| 331 (8)| 00:00:01 |

——————————————————————————–

——————————

Predicate Information (identified by operation id):

—————————————————

5 – filter(BITAND(“S”.”XPFLAGS”,8388608)=8388608)

6 – access(“S”.”OBJ#”=:B1)

8 – access(“EO”.”OBJ#”=:B1)

9 – filter(“O”.”TYPE#”<>4 AND “O”.”TYPE#”<>5 AND “O”.”TYPE#”<>7 AND “O”.”TYPE

#”<>8 AND

“O”.”TYPE#”<>9 AND “O”.”TYPE#”<>11 AND “O”.”TYPE#”<>12 AND “O”.”TY

PE#”<>13 AND “O”.”TYPE#”<>14 AND

“O”.”TYPE#”<>22 AND “O”.”TYPE#”<>87 AND “O”.”TYPE#”<>88 OR BITAND(

“U”.”SPARE1″,16)=0 OR

(“O”.”TYPE#”=4 OR “O”.”TYPE#”=5 OR “O”.”TYPE#”=7 OR “O”.”TYPE#”=8

OR “O”.”TYPE#”=9 OR “O”.”TYPE#”=10

OR “O”.”TYPE#”=11 OR “O”.”TYPE#”=12 OR “O”.”TYPE#”=13 OR “O”.”TYPE

#”=14 OR “O”.”TYPE#”=22 OR

“O”.”TYPE#”=87) AND (SYS_CONTEXT(‘userenv’,’current_edition_name’)

=’ORA$BASE’ AND “U”.”TYPE#”<>2 OR

“U”.”TYPE#”=2 AND “U”.”SPARE2″=TO_NUMBER(SYS_CONTEXT(‘userenv’,’cu

rrent_edition_id’)) OR EXISTS

(SELECT 0 FROM SYS.”USER$” “U2″,SYS.”OBJ$” “O2” WHERE “O2”.”OWNER#

“=”U2″.”USER#” AND “O2”.”TYPE#”=88

AND “O2”.”DATAOBJ#”=:B1 AND “U2”.”TYPE#”=2 AND “U2”.”SPARE2″=TO_NU

MBER(SYS_CONTEXT(‘userenv’,’current_

edition_id’)))))

10 – access(“O”.”SPARE3″=”U”.”USER#”)

12 – access(“O”.”OWNER#”=”U”.”USER#”)

14 – filter(“O”.”TYPE#”<>10 AND “O”.”NAME”<>’_NEXT_OBJECT’ AND

“O”.”NAME”<>’_default_auditing_options_’ AND “O”.”LINKNAME” IS NUL

L AND BITAND(“O”.”FLAGS”,128)=0)

16 – access(“U2”.”TYPE#”=2 AND “U2”.”SPARE2″=TO_NUMBER(SYS_CONTEXT(‘userenv’,’

current_edition_id’)))

filter(“U2”.”TYPE#”=2 AND “U2”.”SPARE2″=TO_NUMBER(SYS_CONTEXT(‘userenv’,’

current_edition_id’)))

17 – access(“O2”.”DATAOBJ#”=:B1 AND “O2”.”TYPE#”=88 AND “O2″.”OWNER#”=”U2”.”US

ER#”)

21 – access(“L”.”OWNER#”=”U”.”USER#”)

Statistics

———————————————————-

11 recursive calls

1279 db block gets

2384 consistent gets

1251 physical reads

928 redo size

528 bytes sent via SQL*Net to client

500 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

SQL>

The lines in bold font are showing the temp table transformation. If the alias “t” is used repeatedly in the script, the “select * from dba_objects” will not be re-executed but the results will be loaded from the temp table. Now, there is a new version of the same trick:

1 with t as (select /*+ result_cache */ * from dba_objects)

2* select count(*) from t

SQL> /

COUNT(*)

———-

87661

Elapsed: 00:00:01.90

Execution Plan

———————————————————-

Plan hash value: 1250653294

——————————————————————————–

——-

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Tim

e |

——————————————————————————–

——-

| 0 | SELECT STATEMENT | | 1 | | 237 (24)| 00:

00:01 |

| 1 | SORT AGGREGATE | | 1 | | |

|

| 2 | VIEW | DBA_OBJECTS | 87374 | | 237 (24)| 00:

00:01 |

| 3 | UNION-ALL | | | | |

|

|* 4 | FILTER | | | | |

|

|* 5 | HASH JOIN | | 87373 | 9385K| 236 (24)| 00:

00:01 |

| 6 | INDEX FULL SCAN | I_USER2 | 99 | 396 | 1 (0)| 00:

00:01 |

|* 7 | HASH JOIN | | 87373 | 9044K| 230 (23)| 00:

00:01 |

| 8 | INDEX FULL SCAN | I_USER2 | 99 | 2178 | 1 (0)| 00:

00:01 |

|* 9 | TABLE ACCESS FULL| OBJ$ | 87373 | 7167K| 224 (21)| 00:

00:01 |

| 10 | NESTED LOOPS | | 1 | 29 | 2 (0)| 00:

00:01 |

|* 11 | INDEX SKIP SCAN | I_USER2 | 1 | 20 | 1 (0)| 00:

00:01 |

|* 12 | INDEX RANGE SCAN | I_OBJ4 | 1 | 9 | 1 (0)| 00:

00:01 |

| 13 | NESTED LOOPS | | 1 | 17 | 1 (0)| 00:

00:01 |

| 14 | INDEX FULL SCAN | I_LINK1 | 1 | 13 | 0 (0)| 00:

00:01 |

|* 15 | INDEX RANGE SCAN | I_USER2 | 1 | 4 | 1 (0)| 00:

00:01 |

——————————————————————————–

——-

Predicate Information (identified by operation id):

—————————————————

4 – filter(“O”.”TYPE#”<>4 AND “O”.”TYPE#”<>5 AND “O”.”TYPE#”<>7 AND

“O”.”TYPE#”<>8 AND “O”.”TYPE#”<>9 AND “O”.”TYPE#”<>11 AND “O”.”TYP

E#”<>12 AND

“O”.”TYPE#”<>13 AND “O”.”TYPE#”<>14 AND “O”.”TYPE#”<>22 AND “O”.”T

YPE#”<>87

AND “O”.”TYPE#”<>88 OR BITAND(“U”.”SPARE1″,16)=0 OR (“O”.”TYPE#”=4

OR

“O”.”TYPE#”=5 OR “O”.”TYPE#”=7 OR “O”.”TYPE#”=8 OR “O”.”TYPE#”=9 O

R

“O”.”TYPE#”=10 OR “O”.”TYPE#”=11 OR “O”.”TYPE#”=12 OR “O”.”TYPE#”=

13 OR

“O”.”TYPE#”=14 OR “O”.”TYPE#”=22 OR “O”.”TYPE#”=87) AND

(SYS_CONTEXT(‘userenv’,’current_edition_name’)=’ORA$BASE’ AND “U”.

“TYPE#”<>2

OR “U”.”TYPE#”=2 AND “U”.”SPARE2″=TO_NUMBER(SYS_CONTEXT(‘userenv’,

‘current_edit

ion_id’)) OR EXISTS (SELECT 0 FROM SYS.”USER$” “U2″,SYS.”OBJ$” “O

2″ WHERE

“O2″.”OWNER#”=”U2″.”USER#” AND “O2”.”TYPE#”=88 AND “O2″.”DATAOBJ#”

=:B1 AND

“U2”.”TYPE#”=2 AND “U2”.”SPARE2″=TO_NUMBER(SYS_CONTEXT(‘userenv’,’

current_editi

on_id’)))))

5 – access(“O”.”SPARE3″=”U”.”USER#”)

7 – access(“O”.”OWNER#”=”U”.”USER#”)

9 – filter(“O”.”TYPE#”<>10 AND “O”.”NAME”<>’_NEXT_OBJECT’ AND

“O”.”NAME”<>’_default_auditing_options_’ AND “O”.”LINKNAME” IS NUL

L AND

BITAND(“O”.”FLAGS”,128)=0)

11 – access(“U2”.”TYPE#”=2 AND “U2”.”SPARE2″=TO_NUMBER(SYS_CONTEXT(‘userenv’,

‘current_edition_id’)))

filter(“U2”.”TYPE#”=2 AND “U2”.”SPARE2″=TO_NUMBER(SYS_CONTEXT(‘userenv’,

‘current_edition_id’)))

12 – access(“O2”.”DATAOBJ#”=:B1 AND “O2”.”TYPE#”=88 AND

“O2″.”OWNER#”=”U2″.”USER#”)

15 – access(“L”.”OWNER#”=”U”.”USER#”)

Statistics

———————————————————-

0 recursive calls

0 db block gets

1115 consistent gets

0 physical reads

0 redo size

528 bytes sent via SQL*Net to client

500 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

SQL>

The difference is in the /*+ result_cache */ hint instead of /*+ materialize /. The purpose is exactly the same, the difference in general should be marginal, coming from not having to create a temporary object in the dictionary. However, it is my general experience that the scripts with the /*+ result_cache */ hint behave a little bit better and perform a little bit faster than with the old material girl version.

The numbers in the script above prove nothing, because the table rows have already been read by the previous version, so the fact that the /*+ materialize */ version did some physical reads and the /*+ result_cache */ version didn’t didn’t do any physical reads was to be expected and proves nothing. Again, it is my impression that the result cache behaves better than the “material girl” version.

Posted in Uncategorized | Tagged | 2 Comments

After startup trigger on RAC

Recently, a colleague of mine had some problems with pinning application procedures into the shared pool. His database was upgraded to RAC and he wanted to pin the application procedures and packages into shared pool upon the database startup.
The non-RAC version of the database was using a shell script, something like $ORACLE_HOME/local/scripts/pin_procs.sh in the script that was starting DB when the system was booted
However, RAC starts the database automatically and no user scripts are invoked during startup. The alternative mechanism is to use a startup database trigger. The only question that remains is whether the trigger will file once for each instance or once for the database? The trigger will fire once for each instance. Let’s demonstrate the statement:

mgogala@umajor:~$ ssh oracle@rac1
Last login: Sat Aug 8 19:36:48 2015
[oracle@rac1 ~]$ srvctl start db -d orcl
[oracle@rac1 ~]$ srvctl status db -d orcl
Instance orcl2 is running on node rac1
Instance orcl1 is running on node rac2
[oracle@rac1 ~]$ srvctl config db -d orcl
Database unique name: orcl
Database name: orcl
Oracle home: /home/oracle/app/oracle/product/11.2.0/dbhome_1
Oracle user: oracle
Spfile: +DATA/orcl/spfileorcl.ora
Domain:
Start options: open
Stop options: immediate
Database role: PRIMARY
Management policy: AUTOMATIC
Server pools: orcl
Database instances: orcl2,orcl1
Disk Groups: DATA,REDO
Mount point paths:
Services:
Type: RAC
Database is administrator managed
[oracle@rac1 ~]$

This is a little 11.2.0.4 RAC database, running on two nodes. The proof will be achieved by creating a trigger which inserts the instance id and the host name into a table. If the table contains only a single record, the trigger have fired only once. If there are two records, with two different instance numbers and machine names, the trigger has fired twice, just as was the original statement. So, let’s first create a table in the SCOTT schema:
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options

SQL> create table startup(
2 inst_num integer,
3 inst_host varchar2(128));

Table created.

Elapsed: 00:00:00.11
SQL> grant insert on startup to system;

Grant succeeded.

Elapsed: 00:00:00.01

Next comes the trigger in the SYSTEM schema, because login triggers can only be created by the schema with the DBA privilege.

SQL> connect system@rac11
Enter password:
Connected.
CREATE OR REPLACE TRIGGER system.start_me_up AFTER startup ON DATABASE
DECLARE
instance_num INTEGER;
host VARCHAR2(128);
BEGIN
SELECT instance_number,host_name INTO INSTANCE_NUM,HOST FROM v$instance;
INSERT INTO scott.startup VALUES (instance_num,host);
END;
9 /

Trigger created.

Elapsed: 00:00:00.26

Now, the moment of truth. Let’s restart the database and see what is in the SCOTT.STARTUP table. First, the restart:

[oracle@rac1 ~]$ srvctl stop db -d orcl -o immediate
[oracle@rac1 ~]$ srvctl status db -d orcl
Instance orcl2 is not running on node rac1
Instance orcl1 is not running on node rac2
[oracle@rac1 ~]$ srvctl start db -d orcl
[oracle@rac1 ~]$ srvctl status db -d orcl
Instance orcl2 is running on node rac1
Instance orcl1 is running on node rac2
[oracle@rac1 ~]$

Now, let’s check SCOTT.STARTUP:
mgogala@umajor:~$ sqlplus scott/tiger@rac11

SQL*Plus: Release 12.1.0.2.0 Production on Wed Aug 12 18:32:01 2015

Copyright (c) 1982, 2014, Oracle. All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options

SQL> column inst_host format a10;
SQL> select * from startup;

INST_NUM INST_HOST
---------- ----------
2 rac1
1 rac2

Elapsed: 00:00:00.01
SQL>

The table contains two records, once for each instance. That proves that the startup trigger will fire once for each instance. This also provides the mechanism for doing different things after starting different instances because it would be trivial to add IF … THEN clause based on the instance number. However, in this particular case, the task was to pin the same set of the application procedures in both instances. This was accomplished by the database trigger.

Posted in Uncategorized | 1 Comment

ASM 12c, OCR and voting devices II

I finished the installation of 12c cluster and noticed that I haven’t been asked for voting and registry devices as was previously the case. I had to create a single disk group. John Franklin, from LinkedIn RAC SIG suggested running ocrcheck command, so I did:

[grid@rac1 ~]$ ocrcheck -details
Status of Oracle Cluster Registry is as follows :
Version : 4
Total space (kbytes) : 409568
Used space (kbytes) : 1612
Available space (kbytes) : 407956
ID : 1368218241
Device/File Name : +DATA/scan11/OCRFILE/registry.255.886021581
Device/File integrity check succeeded

Device/File not configured

Device/File not configured

Device/File not configured

Device/File not configured

Cluster registry integrity check succeeded

Logical corruption check bypassed due to non-privileged user

[grid@rac1 ~]$

So OCR file is still there, only lumped as a single file in the disk group created during the installation. So, let’s see what else is there:

ASMCMD> ls +DATA
ASM/
ORCL/
_MGMTDB/
orapwasm
scan11/

ORCL is the name of my Oracle 11.2.0.4 database, scan11 is the cluster name. Registry is precisely where ocrcheck said it would be:

ASMCMD> ls scan11
ASMPARAMETERFILE/
OCRFILE/
ASMCMD> ls scan11/OCRFILE
REGISTRY.255.886021581
ASMCMD>

What in the world is MGMTDB? Turns out that it is pretty well documented:

Mike Dietrich’s blog

Management database contains cluster health information and is a full fledged Oracle database which uses 4.5GB:

I finished the installation of 12c cluster and noticed that I haven’t been asked for voting and registry devices as was previously the case. I had to create a single disk group. John Franklin, from LinkedIn RAC SIG suggested running ocrcheck command, so I did:

[grid@rac1 ~]$ ocrcheck -details
Status of Oracle Cluster Registry is as follows :
Version : 4
Total space (kbytes) : 409568
Used space (kbytes) : 1612
Available space (kbytes) : 407956
ID : 1368218241
Device/File Name : +DATA/scan11/OCRFILE/registry.255.886021581
Device/File integrity check succeeded

Device/File not configured

Device/File not configured

Device/File not configured

Device/File not configured

Cluster registry integrity check succeeded

Logical corruption check bypassed due to non-privileged user

[grid@rac1 ~]$

So OCR file is still there, only lumped as a single file in the disk group created during the installation. So, let’s see what else is there:

ASMCMD> ls +DATA
ASM/
ORCL/
_MGMTDB/
orapwasm
scan11/

ORCL is the name of my Oracle 11.2.0.4 database, scan11 is the cluster name. Registry is precisely where ocrcheck said it would be:

ASMCMD> ls scan11
ASMPARAMETERFILE/
OCRFILE/
ASMCMD> ls scan11/OCRFILE
REGISTRY.255.886021581
ASMCMD>

What in the world is MGMTDB? Turns out that it is pretty well documented:

Mike Dietrich’s blog

Management database contains cluster health information and is a full fledged Oracle database which uses 4.5GB:

ASMCMD> du _MGMTDB
Used_MB Mirror_used_MB
4365 4365
ASMCMD>

Ti instance is, of course running:

[grid@rac1 ~]$ ps -ef|grep smon
grid 3579 1 0 10:02 ? 00:00:00 asm_smon_+ASM2
root 4818 1 0 10:02 ? 00:00:17 /app/grid/12.1.0/bin/osysmond.bi
grid 5388 1 0 10:03 ? 00:00:00 mdb_smon_-MGMTDB

So, let’s see what’s in there:

[grid@rac1 ~]$ export ORACLE_SID=”-MGMTDB”
[grid@rac1 ~]$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.2.0 Production on Mon Jul 27 10:37:43 2015

Copyright (c) 1982, 2014, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 – 64bit Production
With the Partitioning, Automatic Storage Management and Advanced Analytics options

SQL> select username from dba_users;

USERNAME
——————————————————————————–
ANONYMOUS
DBSNMP
WMSYS
XDB
APPQOSSYS
GSMADMIN_INTERNAL
GSMCATUSER
SYSBACKUP
OUTLN
DIP
SYSDG

USERNAME
——————————————————————————–
ORACLE_OCM
SYSKM
XS$NULL
GSMUSER
AUDSYS
SYSTEM
SYS

18 rows selected.

SQL> alter session set current_schema=GSMADMIN_INTERNAL;

Session altered.

SQL> desc database
Name Null? Type
—————————————– ——– —————————-
NAME NOT NULL VARCHAR2(30)
POOL_NAME VARCHAR2(30)
REGION_NUM NUMBER
GSM_PASSWORD NOT NULL VARCHAR2(30)
CONNECT_STRING NOT NULL VARCHAR2(256)
DATABASE_NUM NOT NULL NUMBER
STATUS NOT NULL CHAR(1)
SCAN_ADDRESS VARCHAR2(256)
ONS_PORT NUMBER
NUM_ASSIGNED_INSTANCES NOT NULL NUMBER
SRLAT_THRESH NUMBER
CPU_THRESH NUMBER
VERSION VARCHAR2(30)
DB_TYPE CHAR(1)
ENCRYPTED_GSM_PASSWORD RAW(2000)

SQL> select name,version,db_type from database;

no rows selected

SQL> select * from database;

no rows selected

SQL> select * from verify_history
2 /

no rows selected

SQL>

So, nothing is in there yet. I will have to follow the documentation and set up monitoring and diagnostic data collection.  I am slightly worried because another full fledged EE Oracle instance is added to my RAC nodes, thereby increasing CPU and memory consumption. On the other hand, the metrics described in the manual page looks very useful. A system monitoring repository can be a treasure trove of the information. My feelings are mixed, let’s wait and see.

Posted in Uncategorized | Leave a comment

ASM 12c – no voting/quorum device and OCR?

I installed my first 12c ASM (database is still 11.2.0.4) and I made the 11G disk layout: 2GB for voting/quorum, 2 GB for OCR. However, the installation procedure did not ask me for the voting and OCR devices. ASM came right up without them. So, the devices are not needed for 12c? What about upgrading from 11g, which did need the devices? The “crsctl” utility confirms that voting and OCR devices are not there:

——————————————————————————–
Name Target State Server State details
——————————————————————————–
Local Resources
——————————————————————————–
ora.ACFS.ORASHARE.advm
ONLINE ONLINE rac1 Volume device /dev/a
sm/orashare-453 is o
nline,STABLE
ONLINE ONLINE rac2 Volume device /dev/a
sm/orashare-453 is o
nline,STABLE
ora.ACFS.dg
ONLINE ONLINE rac1 STABLE
ONLINE ONLINE rac2 STABLE
ora.DATA.dg
ONLINE ONLINE rac1 STABLE
ONLINE ONLINE rac2 STABLE
ora.FRA.dg
ONLINE ONLINE rac1 STABLE
ONLINE ONLINE rac2 STABLE
ora.LISTENER.lsnr
ONLINE ONLINE rac1 STABLE
ONLINE ONLINE rac2 STABLE
ora.REDO.dg
ONLINE ONLINE rac1 STABLE
ONLINE ONLINE rac2 STABLE
ora.acfs.orashare.acfs
ONLINE ONLINE rac1 mounted on /orashare
,STABLE
ONLINE ONLINE rac2 mounted on /orashare
,STABLE
ora.asm
ONLINE ONLINE rac1 Started,STABLE
ONLINE ONLINE rac2 Started,STABLE
ora.net1.network
ONLINE ONLINE rac1 STABLE
ONLINE ONLINE rac2 STABLE
ora.ons
ONLINE ONLINE rac1 STABLE
ONLINE ONLINE rac2 STABLE
——————————————————————————–
Cluster Resources
——————————————————————————–
ora.LISTENER_SCAN1.lsnr
1 ONLINE ONLINE rac1 STABLE
ora.LISTENER_SCAN2.lsnr
1 ONLINE ONLINE rac1 STABLE
ora.MGMTLSNR
1 ONLINE ONLINE rac1 169.254.244.71 10.1.
1.10,STABLE
ora.cvu
1 ONLINE ONLINE rac2 STABLE
ora.mgmtdb
1 ONLINE ONLINE rac1 Open,STABLE
ora.oc4j
1 ONLINE ONLINE rac2 STABLE
ora.orcl.db
1 ONLINE ONLINE rac2 Open,STABLE
2 ONLINE ONLINE rac1 Open,STABLE
ora.rac1.vip
1 ONLINE ONLINE rac1 STABLE
ora.rac2.vip
1 ONLINE ONLINE rac2 STABLE
ora.scan1.vip
1 ONLINE ONLINE rac1 STABLE
ora.scan2.vip
1 ONLINE ONLINE rac1 STABLE
——————————————————————————–

That is a very big departure from the classic architecture. Voting and registry devices have been used since the OPS times. The question, still unanswered, is how will CRS determine which node to evict in case of failure. Voting device was used, just as in the “Survivor” show to determine who gets voted off the island.

Posted in Uncategorized | 2 Comments

Oracle Database Transactions and Locking Revealed, by Tom Kyte and Darl Kuhn

I recently came across the book called “Oracle Database Transactions and Locking Revealed” by Tom Kyte and Darl Kuhn. Usually, any new book by Tom Kyte is a big deal and acquires a huge following very quickly. Strangely enough there was only a single review on the Amazon, before I added my own.

For the reasons unknown to me, this book is literally ignored. I haven’t seen posts on the oracle-l about it, on the LinkedIn forums or Usenet. This book is relatively new, became available in November 2014, but it’s enough time for the book to be widely commented or recommended. There are no reasons not to recommend the book. The book is very short, 150 pages, and is not one of those 700+ pages monsters that Oracle books of today frequently turn into. I would wholeheartedly recommend the book to developers, developing Oracle applications. It deals with critically important subjects like locking, transactions, undo and redo.  The only thing missing from the book, which in my opinion should have been there, is flashback.

However, the book is primarily dedicated to applications developers, not meant as an in-depth study for the aspiring DBA hopefuls. The main strength of the book lies precisely in its brevity and clarity. It covers the topics of critical importance for the application development. How many times did I hear the myth about the need to commit frequently? How many times did I see “WHEN OTHERS” exception handler in its most atrocious form (“WHEN OTHERS THEN NULL”)? Tom and Darl do an excellent job explaining these things. They also provide tools to investigate redo and undo, all in 150 pages. Excellent job, must have for any application developer.

Posted in Uncategorized | 1 Comment

PostgreSQL Hints and DBMS_STATS

For those who don’t know,‭ ‬it is now possible to use hints on PgSQL.‭ ‬Here
is how things work:

-‭ ‬Download and install the extension from the home page:

‭  ‬http://sourceforge.jp/projects/pghintplan/

If you are using Red Hat derivative,‭ ‬like me,‭ ‬it’s a simple RPM package.‭ ‬Check the content of the package,‭ ‬like this:

[‬mgogala@pg91‭ ~]‬$‭ ‬rpm‭ ‬-qa|grep pg_hint

pg_hint_plan93-1.1.3-1.el6.x86‭_‬64‭
[‬mgogala@pg91‭ ~]‬$
‭[‬mgogala@pg91‭ ~]‬$‭ ‬rpm‭ ‬-ql pg_hint_plan93-1.1.3-1.el6.x86‭_‬64
/usr/pgsql-9.3/lib/pg_hint_plan.so
/usr/pgsql-9.3/share/extension/pg_hint_plan–1.0–1.1.1.sql
/usr/pgsql-9.3/share/extension/pg_hint_plan–1.1.1–1.1.2.sql
/usr/pgsql-9.3/share/extension/pg_hint_plan–1.1.2–1.1.3.sql
/usr/pgsql-9.3/share/extension/pg_hint_plan–1.1.3.sql
/usr/pgsql-9.3/share/extension/pg_hint_plan.control

Put the following parameters into your postgresql.conf:

shared_preload_libraries‭ = '‬/usr/pgsql-9.3/lib/pg_hint_plan.so‭'
pg_hint_plan.enable_hint_tables‭ = ‬on

Now you need to restart your PostgreSQL and you’re done,‭ ‬the extension is ready to use.‭ ‬It is a good practice to run the following statement:

postgres‭=‬#‭ ‬create extension if not exists pg_hint_plan‭;
CREATE EXTENSION

Now,‭ ‬users can do the following:

mgogala‭=‬#‭ ‬explain select‭ * ‬from emp where empno‭=‬7934‭;
QUERY PLAN
----------------------------------------------------
‭ ‬Seq Scan on emp‭  (‬cost‭=‬0.00..1.18‭ ‬rows‭=‬1‭ ‬width‭=‬43‭)
Filter:‭ (‬empno‭ = ‬7934‭)
(2‭ ‬rows‭)

Without any hints,‭ ‬the planner chooses sequential scan.‭ ‬Now,‭ ‬let’s try with a hint:

mgogala‭=‬#‭ ‬explain select‭ ‬/‭*‬+‭ ‬IndexScan(emp emp_pkey‭) *‬/‭ * ‬from emp where
empno‭=‬7934‭;
QUERY PLAN
---------------------------------------------------------------------
‭ ‬Index Scan using emp_pkey on emp‭  (‬cost‭=‬0.14..8.15‭ ‬rows‭=‬1‭ ‬width‭=‬43‭)
Index Cond:‭ (‬empno‭ = ‬7934‭)
(2‭ ‬rows‭)

Voila,‭ ‬the optimizer hints are ready to use.‭ ‬This works on‭ ‬9.3.6:

mgogala‭=‬#‭ ‬select version‭();

version

——————————————————————————–
——————————-
‭ ‬PostgreSQL‭ ‬9.3.6‭ ‬on x86‭_‬64-unknown-linux-gnu,‭ ‬compiled by gcc‭ (‬GCC‭)
4.4.7‭ ‬20120‭ ‬313‭ (‬Red Hat‭ ‬4.4.7-11‭)‬,‭ ‬64-bit‭ (‬1‭ ‬row‭)

There is also RPM package for‭ ‬9.4.‭ ‬Please note that the planner has correctly told you that the cost of an index scan is higher than the cost of sequential scan.‭ ‬In this particular case,‭ ‬it is correct.‭ ‬The whole table fits into a single block and sequential scan of that block is the fastest method.‭ ‬Index scan needs to read the index root block,‭ ‬then the index leaf block and only then the table block.‭  ‬The optimizer has incorrectly estimated the cost of a sequential scan,‭ ‬because it cannot be‭ “‬0.00‭”‬.‭ ‬That is an example of an optimizer bug and yet another reason to have hints at hand.
There are also cases when the optimizer plan itself goes awry.‭ ‬Any help that can be provided in such situations is beneficial. Hints give you better granularity then‭ “‬set enable_indexscan‭” ‬or similar commands which affect the entire session and can negatively impact the subsequent SQL commands.‭ ‬Hints are not ideal and do require some maintenance between versions,‭ ‬but are sometimes the only solution when performance of your SQL has to be improved quickly.‭ ‬You know your data better than the planner and hints give you the means of overriding an incorrect plan for a single SQL statement.‭ ‬Hints are simply a tool that can be used in fire fighting situations.

It is encouraging to see such extension in a community which was up in arms against the proponents of hints not so long ago.‭ ‬There is still the ridiculous‭ “‬we don’t want hints‭” ‬part on the PostgreSQL wiki,‭ ‬but there is also the‭  ‬extension which allows anyone who does want them to use them.‭ ‬PostgreSQL‭ community has just discovered democracy.

Another interesting PostgreSQL package by the same author is the following:

http://pgdbmsstats.sourceforge.jp/pg_dbms_stats-en.html

That package offers some,‭ ‬but not all,‭ ‬functionality found in Oracle’s DBMS_STATS package,‭ ‬in particular locking and exporting the table stats.‭ ‬That functionality has not been offered by VACUUM utility which PostgreSQL uses to gather stats on the tables.‭

Posted in Uncategorized | Tagged | 3 Comments

Opatch Integration

Oracle 12c came up with one nice new feature: Opatch, the tool known to all database administrators is now integrated into the database in the form of DBMS_QOPATCH package. If the database contains pluggable databases, the package must be executed from the root (CDB$ROOT) level, as user sys.
Also, a minor inconvenience is that there are no tabular results, results are returned as XML. It is a bit cumbersome to work with and I do prefer the traditional Opatch for now. So, let’s make an example:

Screenshot - 11102014 - 05:40:22 PM

The query is “select dbms_qopatch.get_opatch_list() from dual” and it returns results in one monstrous line. There is no nice way to look at the output XML in the SQL Developer, one must cut & paste the entire monstrosity into a 3rd party XML editor:
Screenshot - 11102014 - 05:51:11 PM
This looks like a story similar to V$DIAG_ALERT_EXT, which was available in the last versions of 10G software as an X$ table, to be made both available and useful in version 11G. This XML output is completely useless and very hard to read. The good, old “opatch lsinventory” is still preferred, but it is going to be integrated with the database in not so distant future. For now, DBA_REGISTRY_HISTORY will have to do.

Posted in Uncategorized | Leave a comment