Sunday, September 15, 2013

Use DBMS_SQLTUNE.IMPORT_SQL_PROFILE to force a hint to a query

DBMS_SQLTUNE.IMPORT_SQL_PROFILE is actually the procedure used when you implement a SQL Tuning Advisor's recommendation involving a better execution plan. But the SQL Tuning Advisor may not recommend the execution plan you know is the correct one or may even not recommend a new execution plan. If you know the hint that will improve your query's performance, then you may want to use DBMS_SQLTUNE.IMPORT_SQL_PROFILE to force it.

Let's create a scenario. Firstly, create 2 tables and 1 index in each one.
sqlplus system

SQL*Plus: Release 11.2.0.3.0 Production on Sun Sep 15 20:32:10 2013
Copyright (c) 1982, 2011, Oracle.  All rights reserved.
Enter password: 

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

SQL> CREATE TABLE SYSTEM.OBJECTS AS SELECT * FROM DBA_OBJECTS;
Table created.

SQL> CREATE INDEX SYSTEM.OBJ_NAME ON SYSTEM.OBJECTS(OBJECT_NAME);
Index created.

SQL> CREATE TABLE SYSTEM.SEGMENTS AS SELECT * FROM DBA_SEGMENTS;
Table created.

SQL> CREATE INDEX SYSTEM.SEG_NAME ON SYSTEM.SEGMENTS(SEGMENT_NAME);
Index created.

We will use a query that joins those tables using the indexed columns.
SQL> SET AUTOT TRACEONLY
SQL> SET TIMING ON
SQL> SET LINESIZE 200
SQL> SELECT OBJECT_ID,
       OBJECT_NAME,
       SEGMENT_TYPE,
       TABLESPACE_NAME
  FROM SYSTEM.OBJECTS, SYSTEM.SEGMENTS
 WHERE OBJECT_NAME = SEGMENT_NAME AND SEGMENT_NAME LIKE 'DBA%';

Elapsed: 00:00:00.02

Execution Plan
----------------------------------------------------------
Plan hash value: 98178177

-----------------------------------------------------------------------------------------
| Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |          |   895 |   130K|     5  (20)| 00:00:01 |
|*  1 |  HASH JOIN                   |          |   895 |   130K|     5  (20)| 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| SEGMENTS |   784 | 54880 |     1   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | SEG_NAME |   141 |       |     1   (0)| 00:00:01 |
|   4 |   TABLE ACCESS BY INDEX ROWID| OBJECTS  |  4970 |   383K|     3   (0)| 00:00:01 |
|*  5 |    INDEX RANGE SCAN          | OBJ_NAME |   895 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("OBJECT_NAME"="SEGMENT_NAME")
   3 - access("SEGMENT_NAME" LIKE 'DBA%')
       filter("SEGMENT_NAME" LIKE 'DBA%')
   5 - access("OBJECT_NAME" LIKE 'DBA%')
       filter("OBJECT_NAME" LIKE 'DBA%')


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         14  consistent gets
          0  physical reads
          0  redo size
        892  bytes sent via SQL*Net to client
        520  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed

Now, let's find our query's SQL_ID.
SQL> SELECT SQL_ID, SQL_TEXT
FROM V$SQLAREA
WHERE SQL_TEXT LIKE 'SELECT OBJECT_ID%';

SQL_IDSQL_TEXT
gy6fj888vt27ySELECT OBJECT_ID, OBJECT_NAME, SEGMENT_TYPE, TABLESPACE_NAME FROM SYSTEM.OBJECTS, SYSTEM.SEGMENTS WHERE OBJECT_NAME = SEGMENT_NAME AND SEGMENT_NAME LIKE 'DBA%'

Both indexes are used, but let's assume we want to force full table scans on both tables.

SQL> DECLARE
  2  SQL_FTEXT CLOB;
BEGIN
SELECT SQL_FULLTEXT INTO SQL_FTEXT FROM V$SQLAREA WHERE SQL_ID = 'gy6fj888vt27y';

DBMS_SQLTUNE.IMPORT_SQL_PROFILE(
  SQL_TEXT => SQL_FTEXT,
  PROFILE => SQLPROF_ATTR('FULL(@"SEL$1" "OBJECTS"@"SEL$1") FULL(@"SEL$1" "SEGMENTS"@"SEL$1")'),
  NAME => 'PROFILE_gy6fj888vt27y',
  REPLACE => TRUE,
  FORCE_MATCH => TRUE
);
END;
/
PL/SQL procedure successfully completed.

Let's see the new execution plan.
Execution Plan
----------------------------------------------------------
Plan hash value: 1823853794 [New plan hash value]

-------------------------------------------------------------------------------
| Id  | Operation          | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |          |   895 |   130K|   388   (2)| 00:00:05 |
|*  1 |  HASH JOIN         |          |   895 |   130K|   388   (2)| 00:00:05 |
|*  2 |   TABLE ACCESS FULL| SEGMENTS |   784 | 54880 |    53   (0)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| OBJECTS  |  4970 |   383K|   334   (1)| 00:00:05 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("OBJECT_NAME"="SEGMENT_NAME")
   2 - filter("SEGMENT_NAME" LIKE 'DBA%')
   3 - filter("OBJECT_NAME" LIKE 'DBA%')

Note
-----
   - SQL profile "PROFILE_gy6fj888vt27y" used for this statement [The SQL profile we created, is used]


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1419  consistent gets
        192  physical reads
          0  redo size
        892  bytes sent via SQL*Net to client
        520  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed

You've may noticed the hint's format.
/*+ FULL(OBJECTS) FULL(SEGMENTS) */ is equal to 'FULL(@"SEL$1" "OBJECTS"@"SEL$1") FULL(@"SEL$1" "SEGMENTS"@"SEL$1")'.
Similarly, /*+ INDEX(OBJECTS OBJ_NAME) */ is equal to 'INDEX(@"SEL$1" "OBJECTS"@"SEL$1" "OBJ_NAME")'.

Tuesday, June 4, 2013

Upgrade from OEM 11g to 12c: Step DeployAgentNotRequired ignores agent deployment

We created a new OEM 12c [12.1.0.2.2], using the 2-system upgrade approach from our OEM 11g.

I tried to run the "Deploy and Configure Agent" step on 2 servers A and B and the installation proceeded only to server A. For server B, I was getting a "DeployAgentNotRequired" step with output "Ignoring deployment".

The problem was that there is wrong information in the repository and OEM considered some agents as NFS shared, even though they were not.

Execute the following query as SYSMAN in your OEM 11g repository database and identify which of those agents considered as NFS shared, actually are not.
SELECT TARGET_NAME, MASTER_AGENT_GUID, TARGET_GUID, IS_SHARED
FROM SYSMAN.PRE_UPGC_AGT_STAT_MGMT
WHERE IS_SHARED=1;

Keep the TARGET_NAME of those agents (for our example "B:3872") and set IS_SHARED=0 for them:
UPDATE SYSMAN.PRE_UPGC_AGT_STAT_MGMT
SET IS_SHARED = '0', MASTER_AGENT_GUID=TARGET_GUID
WHERE TARGET_NAME='B:3872';

COMMIT;

Also, check their predeployment status [PRE_DEP_STATUS column] and if the value is STATUS_SUCCESS, change it to STATUS_FAILED:
SELECT TARGET_NAME, PRE_DEP_STATUS
FROM SYSMAN.PRE_UPGC_AGT_STAT_MGMT
WHERE TARGET_NAME = 'B:3872';

UPDATE SYSMAN.PRE_UPGC_AGT_STAT_MGMT
SET PRE_DEP_STATUS='STATUS_FAILED'
WHERE TARGET_NAME = 'B:3872';

COMMIT;

Now, retry the "Deploy and Configure Agent" step for those servers.

Wednesday, April 24, 2013

Upgrade from OEM 11g to 12c: Step unzipAndDeploySoftware fails

We created a new OEM 12c [12.1.0.2.2], using the 2-system upgrade approach from our OEM 11g.

I tried to run the "Deploy and Configure Agent" step on a Linux 64-bit machine and unzipAndDeploySoftware step failed with error:
Check complete: Failed <<<<
Problem: The 32bit software cannot be installed on a 64 bit platform. Similarly the vice-versa is also true where 64bit product cannot be installed on a 32bit machine.
Recommendation: Please install the software on a 32-bit machine if the product is 32bit, otherwise install the product on the 64bit machine if it is a 64bit software.

This is Bug 15995299.
The problem is the OS has been discovered as a Linux 32-bit by the upgrade process.
SELECT TARGET_NAME, PLATFORM_ID, PLATFORM_NAME, CURRENT_VERSION
FROM SYSMAN.PRE_UPGC_AGT_STAT_MGMT
WHERE TARGET_NAME='your_server:3872';

TARGET_NAMEPLATFORM_IDPLATFORM_NAMECURRENT_VERSION
your_server:387246Linux x8611.1.0.1.0

Also, the targets which are monitored by that agent have wrong information:
SELECT EMD_URL, AGENT_NAME, TARGET_NAME, TARGET_TYPE, PLATFORM_ID, PLATFORM_NAME
FROM SYSMAN.PRE_UPGC_TGT_SW
WHERE AGENT_NAME='your_server:3872';

EMD_URLAGENT_NAMETARGET_NAMETARGET_TYPEPLATFORM_IDPLATFORM_NAME
https://your_server:3872/emd/main/your_server:3872your_server:3872oracle_emd46Linux x86
https://your_server:3872/emd/main/your_server:3872your_serverhost46Linux x86

You have to update these tables with the correct OS information:
UPDATE SYSMAN.PRE_UPGC_AGT_STAT_MGMT
    SET PLATFORM_ID='226', PLATFORM_NAME='Linux x86-64'
WHERE TARGET_NAME ='your_server:3872';

UPDATE SYSMAN.PRE_UPGC_TGT_SW SW
SET (PLATFORM_ID,PLATFORM_NAME,OS_VERSION ) =
(SELECT DISTINCT AGT.PLATFORM_ID,AGT.PLATFORM_NAME,AGT.OS_VERSION 
FROM SYSMAN.PRE_UPGC_AGT_STAT_MGMT AGT, SYSMAN.PRE_UPGC_TGT_SW TGT
WHERE TGT.TARGET_GUID=AGT.TARGET_GUID AND SW.EMD_URL=TGT.EMD_URL);

COMMIT;

 Rerun the "Deploy and Configure Agent" step for the particular agent.

You may also check Oracle Note 1519366.1: EM 12c: PreUpgrade Console shows Linux 64-bit Host As 32-bit for RHEL / OEL 5 64-bit servers.