Team LiB   Previous Section   Next Section

14.2 Avoid Unnecessary Parsing

Before your SQL can be executed by Oracle, it needs to be parsed. The importance of parsing when it comes to tuning SQL lies in the fact that no matter how many times a given SQL statement is executed, it needs to be parsed only once. During parsing, the following steps are performed (not necessarily in the sequence shown):

  • The syntax of the SQL statement is verified.

  • The data dictionary is searched to verify table and column definitions.

  • The data dictionary is searched to verify security privileges on relevant objects.

  • Parse locks are acquired on the relevant objects.

  • The optimal execution plan is determined.

  • The statement is loaded into the shared SQL area (also known as the library cache) in the shared pool of the system global area (SGA). The execution plan and parse information are saved here in case the same statement is executed once again.

If a SQL statement involves any remote objects (e.g., database links) then these steps are repeated for the remote objects. As you can see, lots of work is performed during the parsing of a SQL statement. However, a statement is parsed only if Oracle doesn't find an identical SQL statement already in the shared SQL area (library cache) of the SGA.

Before parsing a SQL statement, Oracle searches the library cache for an identical SQL statement. If Oracle finds an exact match, there is no need to parse the statement again. However, if an identical SQL statement is not found, Oracle goes through all the aforementioned steps to parse the statement.

The most important keyword in the previous paragraph is "identical." To share the same SQL area, two statements need to be truly identical. Two statements that look similar, or that return the same result, need not be identical. To be truly identical, the statements must:

  • Have the same uppercase and lowercase characters.

  • Have the same whitespace and newline characters.

  • Reference the same objects using the same names, which must in turn have the same owners.

If there is a possibility that your application executes the same (or similar) SQL statements multiple times, by all means try to avoid unnecessary parsing. This will improve the overall performance of your applications. The following techniques can help you reduce SQL parsing:

  • Use bind variables.

  • Use table aliases.

14.2.1 Using Bind Variables

When multiple users use an application, they actually execute the same set of SQL statements over and over, but with different data values. For example, one customer service representative may be executing the following statement:

SELECT * FROM CUSTOMER WHERE CUST_NBR = 121;

while another customer service representative will be executing:

SELECT * FROM CUSTOMER WHERE CUST_NBR = 328;

These two statements are similar, but not "identical"—the customer ID numbers are different, therefore Oracle has to parse twice.

Because the only difference between these statements is the value used for the customer number, this application could be rewritten to use bind variables. In that case, the SQL statement in question could be as follows:

SELECT * FROM CUSTOMER WHERE CUST_NBR = :X;

Oracle needs to parse this statement only once. The actual customer numbers would be supplied after parsing for each execution of the statement. Multiple, concurrently executing programs could share the same copy of this SQL statement while at the same time supplying different customer number values.

In a multi-user application, situations such as the one described here are very common, and overall performance can be significantly improved by using bind variables, thereby reducing unnecessary parsing.

14.2.2 Using Table Aliases

The use of table aliases can help to improve the performance of your SQL statements. Before getting into the performance aspects of table aliases, let's quickly review what table aliases are and how they are used.

When you select data from two or more tables, you should specify which table each column belongs to. Otherwise, if the two tables have columns with the same name, you will end up with an error:

SELECT CUST_NBR, NAME, ORDER_NBR
FROM CUSTOMER, CUST_ORDER;
SELECT CUST_NBR, NAME, ORDER_NBR
       *
ERROR at line 1:
ORA-00918: column ambiguously defined

The error in this case occurs because both the CUSTOMER and CUST_ORDER tables have columns named CUST_NBR. Oracle can't tell which CUST_NBR column you are referring to. To fix this problem, you could rewrite this statement as follows:

SELECT CUSTOMER.CUST_NBR, CUSTOMER.NAME, CUST_ORDER.ORDER_NBR
FROM CUSTOMER, CUST_ORDER
WHERE CUSTOMER.CUST_NBR = CUST_ORDER.CUST_NBR;

  CUST_NBR NAME                            ORDER_NBR
---------- ------------------------------ ----------
         1 Cooper Industries                    1001
         1 Cooper Industries                    1000
         5 Gentech Industries                   1002
         4 Flowtech Inc.                        1003
         4 Flowtech Inc.                        1004
         8 Zantech Inc.                         1005
         1 Cooper Industries                    1006
         5 Gentech Industries                   1007
         5 Gentech Industries                   1008
         1 Cooper Industries                    1009
         1 Cooper Industries                    1012
         1 Cooper Industries                    1011
         5 Gentech Industries                   1015
         4 Flowtech Inc.                        1017
         4 Flowtech Inc.                        1019
         8 Zantech Inc.                         1021
         1 Cooper Industries                    1023
         5 Gentech Industries                   1025
         5 Gentech Industries                   1027
         1 Cooper Industries                    1029

20 rows selected.

Note the use of the table name to qualify each column name. This eliminates any ambiguity as to which CUST_NBR column the query is referring to.

Instead of qualifying column names with full table names, you can use table aliases, as in the following example:

SELECT C.CUST_NBR, C.NAME, O.ORDER_NBR
FROM CUSTOMER C, CUST_ORDER O
WHERE C.CUST_NBR = O.CUST_NBR;

  CUST_NBR NAME                            ORDER_NBR
---------- ------------------------------ ----------
         1 Cooper Industries                    1001
         1 Cooper Industries                    1000
         5 Gentech Industries                   1002
         4 Flowtech Inc.                        1003
         4 Flowtech Inc.                        1004
         8 Zantech Inc.                         1005
         1 Cooper Industries                    1006
         5 Gentech Industries                   1007
         5 Gentech Industries                   1008
         1 Cooper Industries                    1009
         1 Cooper Industries                    1012
         1 Cooper Industries                    1011
         5 Gentech Industries                   1015
         4 Flowtech Inc.                        1017
         4 Flowtech Inc.                        1019
         8 Zantech Inc.                         1021
         1 Cooper Industries                    1023
         5 Gentech Industries                   1025
         5 Gentech Industries                   1027
         1 Cooper Industries                    1029

20 rows selected.

The letters "C" and "O" in this example are table aliases. You can specify these aliases following their respective table names in the FROM clause, and they can be used everywhere else in the query in place of the table name. Table aliases provide a convenient shorthand notation, allowing your queries to be more readable and concise.

Table aliases are not limited to one character in length. Table aliases can be up to 30 characters in length.

An important thing to remember while using table aliases is that if you define aliases in the FROM clause, you must use only those aliases, and not the actual table names, in the rest of the query. If you alias a table, and then use the actual table name in a query, you will encounter errors. For example:

SELECT C.CUST_NBR, C.NAME, O.ORDER_NBR
FROM CUSTOMER C, CUST_ORDER O
WHERE CUSTOMER.CUST_NBR = CUST_ORDER.CUST_NBR;
WHERE CUSTOMER.CUST_NBR = CUST_ORDER.CUST_NBR
                                     *
ERROR at line 3:
ORA-00904: invalid column name

The column CUST_NBR appears in both the CUSTOMER and CUST_ORDER tables. Without proper qualification, this column is said to be "ambiguously defined" in the query. Therefore, you must qualify the CUST_NBR column with a table alias (or a full table name, if your are not using aliases). However, the other two columns used in the query are not ambiguous. Therefore, the following statement, which only qualifies the CUST_NBR column, is valid:

SELECT C.CUST_NBR, NAME, ORDER_NBR
FROM CUSTOMER C, CUST_ORDER O
WHERE C.CUST_NBR = O.CUST_NBR;

  CUST_NBR NAME                            ORDER_NBR
---------- ------------------------------ ----------
         1 Cooper Industries                    1001
         1 Cooper Industries                    1000
         5 Gentech Industries                   1002
         4 Flowtech Inc.                        1003
         4 Flowtech Inc.                        1004
         8 Zantech Inc.                         1005
         1 Cooper Industries                    1006
         5 Gentech Industries                   1007
         5 Gentech Industries                   1008
         1 Cooper Industries                    1009
         1 Cooper Industries                    1012
         1 Cooper Industries                    1011
         5 Gentech Industries                   1015
         4 Flowtech Inc.                        1017
         4 Flowtech Inc.                        1019
         8 Zantech Inc.                         1021
         1 Cooper Industries                    1023
         5 Gentech Industries                   1025
         5 Gentech Industries                   1027
         1 Cooper Industries                    1029

20 rows selected.

This is where the performance aspect of using table aliases comes into play. Since the query doesn't qualify the columns NAME and ORDER_NBR, Oracle has to search both the CUSTOMER and CUST_ORDER tables while parsing this statement to find which table each of these columns belongs to. The time required for this search may be negligible for one query, but it does add up if you have a number of such queries to parse. It's good programming practice to qualify all columns in a query with table aliases, even those that are not ambiguous, so that Oracle can avoid this extra search when parsing the statement.

    Team LiB   Previous Section   Next Section