Job Search

Thursday, April 28, 2016

The Magic of Bind Variables

Each time the query is submitted, Oracle first checks in the shared pool to see whether this statement has been submitted before. If it has, the execution plan that this statement previously used is retrieved, and the SQL is executed. If the statement cannot be found in the shared pool, Oracle has to go through the process of parsing the statement, working out the various execution paths and coming up with an optimal access plan before it can be executed. This process is know as a «hard parse» and for OLTP applications can actually take longer to carry out that the DML instruction itself.

Hard parsing is very CPU intensive, and involves obtaining latches on key shared memory areas, which whilst it might not affect a single program running against a small set of data, can bring a multi-user system to it's knees if hundreds of copies of the program are trying to hard parse statements at the same time.

The way to get Oracle to reuse the execution plans for these statements is to use bind variables. Bind variables are substituion variables that are used in place of literals (such as 674, 234, 332) and that have the effect of sending exactly the same SQL to Oracle every time the query is executed.

For example, in our application, we would just submit

SELECT fname, lname, pcode FROM cust WHERE id = :cust_no;

and this time we would be able to reuse the execution plan every time, reducing the latch activity in the SGA, and therefore the total CPU activity, which has the effect of allowing our application to scale up to many users on a large dataset.

Hard-parse vs soft parse
Oracle SQL is parsed before execution, and checked for syntax (and parts of the semantic check) before the SQL is loaded into the library cache.  As opposed to a soft parse (which does not require loading into the shared pool), a hard parse includes these steps:

  1. Loading into shared pool - The SQL source code is loaded into RAM for parsing. (the "hard" parse step)
  2. Syntax parse - Oracle parses the syntax to check for misspelled SQL keywords.
  3. Semantic parse - Oracle verifies all table & column names from the dictionary and checks to see if you are authorized to see the data.
  4. Query Transformation - Oracle will transform complex SQL into simpler, equivalent forms and replace aggregations with materialized views, as appropriate. In earlier releases of Oracle the query_rewrite=true parameter had to be set for materialized view rewriting. 
  5. Optimization - Oracle then creates an execution plan, based on your schema statistics (or maybe with statistics from dynamic sampling in 10g).  Oracle build the decision tree of costs during this period, choosing the path with the lowest perceived cost.
  6. Create executable - Oracle builds an executable file with native file calls to service the SQL query.
  7. Fetch rows - Oracle then executes the native calls to the data files to retrieve the rows and passes them back to the calling program.
Anytime a session issues SQL statement that does not already exist in the shared pool, then Oracle has to do a hard parse. essentially performing all of the above steps.  If the statement already exists, then a soft parse occurs, skipping step 1. 

In a soft parse, Oracle must still perform a syntax parse and semantic check because it is possible that a DDL change altered one of the target tables or views since the SQL statement was originally executed.  In the case of DDL, all related SQL is marked as invalidated.

Oracle gives us the shared_pool_size parm to cache SQL so that we don't have to parse, over-and-over again.  However, SQL can age-out if the shared_pool_size is too small or if it is cluttered with non-reusable SQL (i.e. SQL that has literals "where name = "fred") in the source.  Hence, the shared_pool_size parameter (memory_target in 12c AMM) has an impact of hard parses, because re-entrant SQL can age out of the shared pool.

What the difference between a hard parse and a soft parse in Oracle?  Just the first step, step 1 as shown in red, above.  In other words, a soft parse does not require a shared pool reload (and the associated RAM memory allocation).

Excessive hard parsing can occur when your shared_pool_size is too small (and reentrant SQL is paged out), or when you have non-reusable SQL statements without host variables.

The cursor_sharing parameter for a easy way to make SQL reentrant and remember that you should always use host variables in you SQL so that they can be reentrant

Bind Variables in SQL*Plus
In SQL*Plus you can use bind variables as follows:

SQL> variable deptno number
SQL> exec :deptno := 10
SQL> select * from emp where deptno = :deptno;

What we've done to the SELECT statement now is take the literal value out of it, and replace it with a placeholder (our bind variable), with SQL*Plus passing the value of the bind variable to Oracle when the statement is processed. This bit is fairly straighforward (you declare a bind variable in SQL*Plus, then reference the bind variable in the SELECT statement)

Bind Variables in PL/SQL
Taking PL/SQL first of all, the good news is that PL/SQL itself takes care of most of the issues to do with bind variables, to the point where most code that you write already uses bind variables without you knowing. Take, for example, the following bit of PL/SQL:

create or replace procedure dsal(p_empno in number)
as
  begin
    update emp
    set sal=sal*2
    where empno = p_empno;
    commit;
  end;
/

Now you might be thinking that you've got to replace the p_empno with a bind variable. However, the good news is that every reference to a PL/SQL variable is in fact a bind variable.

Dynamic SQL
In fact, the only time you need to consciously decide to use bind variables when working with PL/SQL is when using Dynamic SQL.
Dynamic SQL, allows you to execute a string containing SQL using the EXECUTE IMMEDIATE command. For next example would always require a hard parse when it is submitted:

create or replace procedure dsal(p_empno in number)
as
  begin
    execute immediate
     'update emp set sal = sal*2 where empno = '||p_empno;
  commit;
  end;
/

The way to use bind variables instead is to change the EXECUTE IMMEDIATE command as follows:

create or replace procedure dsal(p_empno in number)
as
  begin
    execute immediate
     'update emp set
     sal = sal*2 where empno = :x' using p_empno;
  commit;
  end;
/

And that's all there is to it. One thing to bear in mind, though, is that you can't substitute actual object names (tables, views, columns etc) with bind variables - you can only subsitute literals. If the object name is generated at runtime, you'll still need to string concatenate these parts, and the SQL will only match with those already in the shared pool when the same object name comes up. However, whenever you're using dynamic SQL to build up the predicate part of a statement, use bind variables instead and you'll reduce dramatically the amount of latch contention going on.

The Performance Killer
Just to give you a tiny idea of how huge of a difference this can make performance wise, you only need to run a very small test:

Here is the Performance Killer ....

SQL> alter system flush shared_pool;
SQL> set serveroutput on;

declare
      type rc is ref cursor;
      l_rc rc;
      l_dummy all_objects.object_name%type;
      l_start number default dbms_utility.get_time;
  begin
      for i in 1 .. 1000
      loop
          open l_rc for
          'select object_name
             from all_objects
            where object_id = ' || i;
          fetch l_rc into l_dummy;
          close l_rc;
          -- dbms_output.put_line(l_dummy);
      end loop;
      dbms_output.put_line
       (round((dbms_utility.get_time-l_start)/100, 2) ||
        ' Seconds...' );
  end;
/
101.71 Seconds...

and here is the Performance Winner:

declare
      type rc is ref cursor;
      l_rc rc;
      l_dummy all_objects.object_name%type;
      l_start number default dbms_utility.get_time;
  begin
      for i in 1 .. 1000
      loop
          open l_rc for
          'select object_name
             from all_objects
            where object_id = :x'
          using i;
          fetch l_rc into l_dummy;
          close l_rc;
          -- dbms_output.put_line(l_dummy);
      end loop;
      dbms_output.put_line
       (round((dbms_utility.get_time-l_start)/100, 2) ||
        ' Seconds...' );
end;
/
1.9 Seconds...

The fact is that not only does this execute much faster (we spent more time PARSING our queries then actually EXECUTING them!) it will let more users use your system simultaneously.


I hope you all have enjoyed reading this article. Comments are welcome....

Sunday, April 24, 2016

Comparison Oracle RDBMS vs. Oracle NoSQL


Oracle Database (commonly referred to as Oracle RDBMS or simply as Oracle) is an object-relational database management system produced and marketed by Oracle Corporation.

Oracle NoSQL Database is a NoSQL-type distributed key-value database by Oracle Corporation. It provides transactional semantics for data manipulation, horizontal scalability, and simple administration and monitoring.
Oracle NoSQL Database provides a very simple data model to the application developer. Each row is identified by a unique key, and also has a value, of arbitrary length, which is interpreted by the application. The application can manipulate (insert, delete, update, read) a single row in a transaction. The application can also perform an iterative, non-transactional scan of all the rows in the database. 

NoSQL (originally referring to "non SQL" or "non relational") database provides a mechanism for storage and retrieval of data which is modeled in means other than the tabular relations used in relational databases. Such databases have existed since the late 1960s, but did not obtain the "NoSQL" moniker until a surge of popularity in the early twenty-first century, triggered by the needs of Web 2.0 companies such as FaceBook, Google and Amazon.com. NoSQL databases are increasingly used in big data and real-time web applications. NoSQL systems are also sometimes called "Not only SQL" to emphasize that they may support SQL-like query languages.

Comparison Oracle RDBMS vs. Oracle NoSQL
Name
Oracle
Oracle NoSQL
Description
Widely used RDBMS
Key-value store based on Berkeley DB Java Edition
Database model
Relational DBMS
Key-value store
Website
Technical documentation
Developer
Oracle
Oracle
Initial release
1980
2011
Current release
12 Release 1 (12.1.0.2), July 2014
License
commercial 
Open Source 
Database as a Service (DBaaS) 
no
no
Implementation language
C and C++
Java
Server operating systems
AIX
HP-UX
Linux
OS X
Solaris
Windows
z/OS
Linux
OS X
Windows
Data scheme
yes
schema-free
Typing 
yes
no
XML support 
yes
Secondary indexes
yes
no
SQL
yes
no
APIs and other access methods
ODP.NET
Oracle Call Interface (OCI)
JDBC
ODBC
Java API
Supported programming languages
C
C#
C++
Clojure
Cobol
Eiffel
Erlang
Fortran
Groovy
Haskell
Java
JavaScript
Lisp
Objective C
OCaml
Perl
PHP
Python
R
Ruby
Scala
Tcl
Visual Basic
Java
Server-side scripts 
PL/SQL 
Triggers
yes
Partitioning methods 
horizontal partitioning 
Sharding 
Replication methods 
Master-master replication
Master-slave replication
Master-slave replication
MapReduce
no 
no
Consistency concepts 
Immediate Consistency
Eventual Consistency
Immediate Consistency 
Foreign keys 
yes
no
Transaction concepts 
ACID 
configurable 
Concurrency 
yes
yes
Durability 
yes
yes
In-memory capabilities 
yes
User concepts 
fine grained access rights according to SQL-standard
no

I hope you all have enjoyed reading this article. Comments are welcome....

Sunday, April 3, 2016

ORA-01652: unable to extend temp segment by 128 in tablespace

Adding Temp File in Temporary tablespace ORA-01652: unable to extend temp segment by 128 in tablespace

I recently encountered issue ORA-01652 unable to extend temp segment by 128 in tablespace ORCL_TEMP while upgrade of application which is self explanatory.

If you hit above error then check v$sort_segment

SQL> SELECT TABLESPACE_NAME,TOTAL_BLOCKS,USED_BLOCKS,FREE_BLOCKS FROM V$SORT_SEGMENT;

To fix this issue, I added additional 1GB temp file in temporary tablespace reported in error (ORCL_TEMP)

1. Identity name & location of temp file in tablespace
SQL> select * from dba_temp_files where tablespace_name like ‘ORCL_TEMP';

2. Add additional temp file in temporary tablespace

SQL> ALTER TABLESPACE ORCL_TEMP ADD TEMPFILE ‘/u01/ app/oracle/ oradata/ iamdb/ dev_iastemp02.dbf’ size 1024M autoextend on next 10M maxsize 2000M;
SQL> create temporary tablespace TMPACCT2 tempfile '/u02/oradata/acct/tmpacct2-1.dbf'size 10M autoextend on next 10M maxsize 2000M;
SQL> alter user TCICDR TEMPORARY TABLESPACE TMPACCT2;
I hope you all have enjoyed reading this article. Comments are welcome....