Total Pageviews

Thursday, November 17, 2016

Tuning Using Functional Based Index: As Real time Scenario by Ashwani Kumar (Oracle Forensics)

               Oracle Function-Based Indexes

Traditionally, performing a function on an indexed column in the where clause of a query guaranteed an index would not be used. Oracle 8i introduced Function-Based Indexes to counter this problem. Rather than indexing a column, you index the function on that column, storing the product of the function, not the original column data. When a query is passed to the server that could benefit from that index, the query is rewritten to allow the index to be used. The following code samples give an example of the use of Function-Based Indexes.

- Build Test Table
- Build Regular Index
- Build Function-Based Index
- Concatenated Columns

Build Test Table

First we build a test table and populate it with enough data so that use of an index would be advantageous.

CREATE TABLE mydata (
 id          NUMBER(10)    NOT NULL,
 first_name  VARCHAR2(40)  NOT NULL,
 last_name   VARCHAR2(40)  NOT NULL,
 gender      VARCHAR2(1),
 dob         DATE
);
 
BEGIN
  FOR cur_rec IN 1 .. 2000 LOOP
    IF MOD(cur_rec, 2) = 0 THEN
      INSERT INTO mydata 
      VALUES (cur_rec, 'Ashwani' || cur_rec, 'Doe', 'M', SYSDATE);
    ELSE
      INSERT INTO mydata 
      VALUES (cur_rec, 'Richard' || cur_rec, 'Doe', 'F', SYSDATE);
    END IF;
    COMMIT;
  END LOOP;
END;
/
EXEC DBMS_STATS.gather_table_stats(USER, 'mydata', cascade => TRUE);
At this point the table is not indexed so we would expect a full table scan for any query.
SET AUTOTRACE ON
SELECT *
FROM   mydata
WHERE  UPPER(first_name) = 'ASHWANI2';
 
Execution Plan
----------------------------------------------------------
Plan hash value: 2489064024
 
-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |    20 |   540 |     5   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| MYDATA |    20 |   540 |     5   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Build Regular Index

If we now create a regular index on the FIRST_NAME column we see that the index is not used.
CREATE INDEX first_name_idx ON mydata (first_name);
EXEC DBMS_STATS.gather_table_stats(USER, 'mydata', cascade => TRUE);
 
SET AUTOTRACE ON
SELECT *
FROM   mydata
WHERE  UPPER(first_name) = 'ASHWANI2';
 
Execution Plan
----------------------------------------------------------
Plan hash value: 2489064024
 
-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |    20 |   540 |     5   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| MYDATA |    20 |   540 |     5   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Build Function-Based Index

If we now replace the regular index with a function-based index on the FIRST_NAME column we see that the index is used.
DROP INDEX first_name_idx;
CREATE INDEX first_name_idx ON mydata (UPPER(first_name));
EXEC DBMS_STATS.gather_table_stats(USER, 'mydata', cascade => TRUE);
 
-- Later releases set these by default.
ALTER SESSION SET QUERY_REWRITE_INTEGRITY = TRUSTED; 
ALTER SESSION SET QUERY_REWRITE_ENABLED = TRUE;
 
SET AUTOTRACE ON
SELECT *
FROM   mydata
WHERE  UPPER(first_name) = 'ASHWANI2';
   
Execution Plan
----------------------------------------------------------
Plan hash value: 1309354431
 
----------------------------------------------------------------------------------------------
| Id  | Operation                   | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                |     1 |    36 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| MYDATA      |     1 |    36 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | FIRST_NAME_IDX |     1 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------
 The QUERY_REWRITE_INTEGRITY and QUERY_REWRITE_ENABLED parameters must be set or the server will not be able to rewrite the queries, and will therefore not be able to use the new index. Later releases have them enabled by default.

Concatenated Columns

This method works for concatenated indexes also.
DROP INDEX first_name_idx;
 
CREATE INDEX first_name_idx ON mydata (gender, UPPER(first_name), dob);
EXEC DBMS_STATS.gather_table_stats(USER, 'mydata', cascade => TRUE);
 
SET AUTOTRACE ON
SELECT *
FROM   mydata
WHERE  gender = 'M'
AND    UPPER(first_name) = 'ASHWANI2';
 
Execution Plan
----------------------------------------------------------
Plan hash value: 1309354431
 
----------------------------------------------------------------------------------------------
| Id  | Operation                   | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                |     1 |    36 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| MYDATA      |     1 |    36 |     3   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | FIRST_NAME_IDX |     1 |       |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------

Remember, function-based indexes require more effort to maintain than regular indexes, so having concatenated indexes in this manner may increase the incidence of index maintenance compared to a function-based index on a single column.

Tuesday, August 2, 2016

How to Check table privileges granted to any USER:

SQL> ---connect to user ashwani
SQL> conn ashwani/ashwani
Connected.
SQL> --create table
SQL> create table mobile (brand varchar2(9));

Table created.

SQL> insert into mobile values ('SONY');

1 row created.

SQL> insert into mobile values ('LUMIA');

1 row created.

SQL> CONN SYS AS SYSDBA
Enter password:
Connected.

SQL> CONN sonu/sonu
Connected.
SQL> select * from ashwani.mobile;
select * from ashwani.mobile
                      *
ERROR at line 1:
ORA-00942: table or view does not exist


SQL>  SELECT 'GRANT '||PRIVILEGE|| ' ON ' ||GRANTOR|| '.' ||TABLE_NAME|| ' TO '  ||GRANTEE|| ';' from dba_tab_privs where grantee in ('SONU') ;
no rows selected

SQL> conn sys as sysdba
Enter password:
Connected.
SQL> grant select on ashwani.mobile to sonu;

Grant succeeded.

SQL>  select privilege,table_name,grantor from dba_tab_privs where grantee='SONU';

PRIVILEGE            TABLE_NAME                     GRANTOR
-------------------- ------------------------------ --------------------
SELECT               MOBILE                         ASHWANI
Or user below dynamic script:


SQL> SELECT 'GRANT '||PRIVILEGE|| ' ON ' ||GRANTOR|| '.' ||TABLE_NAME|| ' TO '  ||GRANTEE|| ';' from dba_tab_privs where grantee in ('SONU') ;
'GRANT'||PRIVILEGE||'ON'||GRANTOR||'.'||TABLE_NAME||'TO'||GRANTEE||';'
--------------------------------------------------------------------------------
GRANT SELECT ON ASHWANI.MOBILE TO SONU;

SQL> CONN sonu/sonu
Connected.
SQL> select * from ashwani.mobile;

BRAND
---------
SONY
LUMIA

Lets grant few other privilege to sonu:

SQL> conn sys as sysdba
Enter password:
Connected.
SQL> grant update on ashwani.mobile to sonu;

Grant succeeded.

SQL>  select privilege,table_name,grantor from dba_tab_privs where grantee='SONU';

PRIVILEGE            TABLE_NAME                     GRANTOR
-------------------- ------------------------------ --------------------
UPDATE               MOBILE                         ASHWANI
SELECT                 MOBILE                         ASHWANI

SQL> SELECT 'GRANT '||PRIVILEGE|| ' ON ' ||GRANTOR|| '.' ||TABLE_NAME|| ' TO '  ||GRANTEE|| ';' from dba_tab_privs where grantee in ('SONU');

'GRANT'||PRIVILEGE||'ON'||GRANTOR||'.'||TABLE_NAME||'TO'||GRANTEE||';'
--------------------------------------------------------------------------------
GRANT UPDATE ON ASHWANI.MOBILE TO SONU;

GRANT SELECT ON ASHWANI.MOBILE TO SONU;

Saturday, July 30, 2016

Scheduler Architecture

Scheduler Architecture

The Scheduler architecture consists of the job table, job coordinator, and the job workers (or slaves, as Oracle calls them). The job table contains information about jobs, such as the job name, program name, and job owner. You can examine the job table by using the DBA_SCHEDULER_JOBS view. The job coordinator regularly looks in the job table to find out what jobs to execute. The job coordinator creates and manages the job worker processes, which actually execute the job. When you create a new job or execute a job, a background process (cjqnnn) wakes up and coordinates the running of the job. When the job coordinator tells a job worker to execute a job, the worker process starts a new database session and starts a transaction. It executes the job, and once completed, it commits and ends the transaction and terminates the database session. The job worker updates the job table, the run count, and the job log table.

Scheduler Privileges:
Oracle creates all jobs, programs, and schedules in the schema of the user that creates these objects, but it creates all the advanced Scheduler components, like job classes, windows, and window groups, at the database level, and their owner is the SYS schema. The SCHEDULER_ADMIN role contains all Scheduler system privileges, with the WITH ADMIN OPTION clause. The DBA role contains the SCHEDULER_ADMIN role. The MANAGE SCHEDULER system privilege lets you do the following:
• Create, drop, and alter job classes, windows, and window groups. • Stop any job. • Start and stop windows prematurely.

Note:  All Scheduler objects are of the form [schema.]name. By default, all scheduler object names are in uppercase, unless you wrap the lowercase names in double quotes, as in "test_job".

You must have the CREATE JOB privilege to create Scheduler components (jobs, schedules, programs, chains, and events). To use the advanced Scheduler components (windows, window groups, and job classes), you need the MANAGE SCHEDULER system privilege. You can assign other users the right to use one of your components by giving them EXECUTE privileges on that component:
• The EXECUTE ANY PROGRAM privilege lets a user execute any program under any schema.
• The EXECUTE ANY CLASS privilege lets you assign a job to any job class.

In order for users to modify Scheduler components, they must use the GRANT ALTER SQL statement for each Scheduler component.
Note : To be able to create a job in a job class you generate, you must have a separate EXECUTE privilege on that job class.

Note the following basic points regarding Scheduler privileges:
• To create a job, you must have the CREATE JOB privilege. • You don’t need any special privileges to specify a schedule, a window or window group, or a program that you own.
• If you specify a program owned by a different user, you must have the EXECUTE privilege on that program, or the EXECUTE ANY PROGRAM system privilege.

Eg.
Creating a Basic Scheduler Job Without a Program or Schedule:
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
JOB_NAME   =>  'test_job',
JOB_TYPE   =>  'PLSQL_BLOCK',
JOB_ACTION         =>  'insert into ashwani.suppliers select * from ashwani.suppliers;',
START_DATE         =>  '11-APRIL-2016 06.30.00 PM',
repeat_interval    => 'FREQ=MINUTELY;INTERVAL=1',
END_DATE           =>  '20-APRIL-2016 07.00.00 PM',
COMMENTS           =>  'Insert new suppliers into the suppliers table',
ENABLED            =>  TRUE);
END;
/
Query to find out the details about TEST_JOB jobs in your database:
SQL>SELECT job_name, program_name FROM dba_scheduler_jobs WHERE job_style='TEST_JOB'

Command for disabling scheduler:

EXEC DBMS_SCHEDULER.DISABLE(name => '"SYS"."TEST_JOB"');

Command for enabling scheduler:

EXEC DBMS_SCHEDULER.ENABLE(name => '"SYS"."TEST_JOB"');

Command for running job manually:

EXEC DBMS_SCHEDULER.RUN_JOB('"SYS"."TEST_JOB"');


Flashback Recovery Techniques

Flashback Recovery Techniques


 Quite often, you may be called upon to help recover from a logical corruption of the database, rather than from a hardware failure. You can use the following flashback techniques in Oracle Database 11g to recover from logical errors:
          Flashback Database: Takes the entire database back to a specific point in time
          Flashback Table: Returns individual tables to a past state
          Flashback Drop: Undoes a DROP TABLE command and recovers the dropped table
          Flashback Query, Flashback Version Query, and Flashback Transaction Query: Retrieve data from a time (or an interval) in the past
          Flashback Transaction Backout: Lets you undo a transaction, together with all its dependent transactions as well, with just a single click in the Database Control
          Flashback Data Archive: Stores history of the changes made to a table, which you can use to make queries using older versions of data and for auditing purposes as well


FLASHBACK TABLE DATA through SCN and TIMESTAMP




19:06:31 SQL> ---FLASHBACK TABLE SCENERIO (SCN)
19:06:43 SQL>
19:06:43 SQL>
19:06:43 SQL>
19:06:44 SQL> SELECT * FROM ASHWANI.KEY;

no rows selected

19:06:53 SQL> INSERT INTO ASHWANI.KEY VALUES ('HELLO1');

1 row created.

19:07:25 SQL> /

1 row created.

19:07:27 SQL> /

1 row created.

19:07:27 SQL> /

1 row created.

19:07:28 SQL> /

1 row created.

19:07:28 SQL> COMMIT;

Commit complete.

19:07:31 SQL> INSERT INTO ASHWANI.KEY VALUES ('HELLO2');

1 row created.

19:07:39 SQL> /

1 row created.

19:07:40 SQL> /

1 row created.

19:07:40 SQL> /

1 row created.

19:07:41 SQL> /

1 row created.

19:07:41 SQL> COMMIT;

Commit complete.

19:07:44 SQL> INSERT INTO ASHWANI.KEY VALUES ('HELLO3');

1 row created.

19:07:49 SQL> /

1 row created.

19:07:51 SQL> /

1 row created.

19:07:52 SQL> /

1 row created.

19:07:52 SQL> /

1 row created.

19:07:53 SQL> COMMIT;

Commit complete.

19:07:55 SQL> SELECT * FROM ASHWANI.KEY;

NAME                                                                           
--------------------------------------------------                              
HELLO2                                                                         
HELLO2                                                                         
HELLO2                                                                         
HELLO2                                                                         
HELLO3                                                                         
HELLO3                                                                         
HELLO3                                                                         
HELLO3                                                                         
HELLO3                                                                         
HELLO1                                                                          
HELLO1                                                                         

NAME                                                                           
--------------------------------------------------                             
HELLO1                                                                         
HELLO1                                                                         
HELLO1                                                                          
HELLO2                                                                         

15 rows selected.

19:08:07 SQL> SELECT * FROM ASHWANI.KEY ORDER BY NAME;

NAME                                                                            
--------------------------------------------------                             
HELLO1                                                                         
HELLO1                                                                          
HELLO1                                                                         
HELLO1                                                                         
HELLO1                                                                         
HELLO2                                                                         
HELLO2                                                                         
HELLO2                                                                         
HELLO2                                                                         
HELLO2                                                                         
HELLO3                                                                         

NAME                                                                            
--------------------------------------------------                             
HELLO3                                                                         
HELLO3                                                                          
HELLO3                                                                         
HELLO3                                                                         

15 rows selected.

19:08:18 SQL> select timestamp_to_scn(to_timestamp('19-FEB-2016 19:07:41','DD-MON-YY  HH24.MI.SS')) from dual;

TIMESTAMP_TO_SCN(TO_TIMESTAMP('19-FEB-201619:07:41','DD-MON-YYHH24.MI.SS'))    
---------------------------------------------------------------------------    
                                                                    4940959    

19:08:51 SQL> FLASHBACK TABLE ASHWANI.KEY TO SCN   5383106;

FLASHBACK TABLE ASHWANI.KEY TO SCN   5381450
                        *
ERROR at line 1:
ORA-08189: cannot flashback the table because row movement is not enabled


SQL> ALTER TABLE ASHWANI.KEY ENABLE ROW MOVEMENT;

Table altered.

19:08:51 SQL> FLASHBACK TABLE ASHWANI.KEY TO SCN   5381450;

Flashback complete.

19:09:03 SQL> SELECT * FROM ASHWANI.KEY ORDER BY NAME;

NAME                                                                           
--------------------------------------------------                             
HELLO1                                                                         
HELLO1                                                                          
HELLO1                                                                         
HELLO1                                                                         
HELLO1                                                                          



19:13:52 SQL> FLASHBACK TABLE ASHWANI.KEY TO TIMESTAMP TO_TIMESTAMP('19-FEB-2016 19:06:44', 'DD-MM-YYYY HH24:MI:SS');

Flashback complete.

19:14:06 SQL> SELECT * FROM ASHWANI.KEY;

no rows selected

19:14:18 SQL>