Home > DBA, Oracle, SQL > Day 9: The Twelve Days of SQL: Physical database design matters

Day 9: The Twelve Days of SQL: Physical database design matters


On the ninth day of Christmas, my true love gave to me
Nine ladies dancing.

Day 9: Physical database design matters (Day 8: Statistics are a double-edged sword)(Day 10: Sometimes the optimizer needs a hint)

Physical database design is the process of designing indexes, partitions, clusters, and materialized views. (Lightstone et al. 2007) Indexes help in restriction, projection, joins of all types, and sorting. Index-organized tables, clusters, and partitions and clusters can be used to organize data and thus reduce physical I/O. Materialized views can be used to perform joins and aggregations ahead of time. In his book Effective Oracle by Design, Tom Kyte quotes Steve Adams as saying: “If a schema has no IOTs or clusters, that is a good indication that no thought has been given to the matter of optimizing data access.”

If a schema has no IOTs or clusters, that is a good indication that no thought has been given to the matter of optimizing data access.

Consider the simple exercise of Day 4: The Twelve Days of SQL: The way you write your query matters. We already have indexes on Empid and Salary and so it would seem that we cannot improve performance any further. But we can get an order of magnitude performance improvement by taking advantage of clusters and materialized views.

CREATE CLUSTER c_salary (salary integer)
SINGLE TABLE SIZE 8192 HASHKEYS 1009;

CREATE MATERIALIZED VIEW LOG ON personnel WITH ROWID;

CREATE MATERIALIZED VIEW LOG ON payroll WITH ROWID;

CREATE MATERIALIZED VIEW mv_salary
CLUSTER c_salary (salary)
REFRESH FAST ON COMMIT
ENABLE QUERY REWRITE
AS
SELECT
  per.ROWID AS per_rowid,
  per.empid,
  per.lname,
  pay.ROWID AS pay_rowid,
  pay.salary
FROM
  personnel per,
  payroll pay
WHERE per.empid = pay.empid;

EXEC DBMS_STATS.gather_table_stats(ownname=>'HR',tabname=>'mv_salary');

SELECT /*+ Uncorrelated subquery with materialized view */ per.empid, per.lname
FROM personnel per
WHERE per.empid IN (SELECT pay.empid
FROM payroll pay
WHERE pay.salary = 199170);

The results are fabulous. The query optimizer automatically takes advantage of the materialized view (automatic query rewrite) and performance improves by an order of magnitude. It took only 13 microseconds to retrieve the data on my laptop running Oracle Database 11g Release 2 within the Developer Days Virtual Machine.

SQL_ID  0qfnuuf6xqjay, child number 0
-------------------------------------
SELECT /*+ Uncorrelated subquery with materialized view */ per.empid,
per.lname FROM personnel per WHERE per.empid IN (SELECT pay.empid FROM
payroll pay WHERE pay.salary = 199170)

Plan hash value: 4094247133

---------------------------------------------------------------------------------------------------------
| Id  | Operation         | Name      | Starts | E-Rows |E-Bytes| Cost  | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |      1 |        |       |     1 |      4 |00:00:00.01 |       2 |
|*  1 |  TABLE ACCESS HASH| MV_SALARY |      1 |     10 |   310 |       |      4 |00:00:00.01 |       2 |
---------------------------------------------------------------------------------------------------------

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

   1 - access("MV_SALARY"."SALARY"=199170)

Note
-----
   - cpu costing is off (consider enabling it)

Here is how the execution time compares with those of the query plans you saw in Day 4: The Twelve Days of SQL: The way you write your query matters:

METHOD                                           SQL_ID        PLAN_HASH_VALUE EXECUTIONS LAST_ELAPSED_TIME LAST_CR_BUFFER_GETS LAST_DISK_READS LAST_OUTPUT_ROWS
------------------------------------------------ ------------- --------------- ---------- ----------------- ------------------- --------------- ----------------
Uncorrelated subquery with materialized view     0qfnuuf6xqjay      4094247133          2                13                   2               0                4
Uncorrelated subquery                            avhtrqsvaay7j      3342999746          2               129                  17               0                4
Aggregate function to check existence (unnested) 8bk6d3udbcbp4       864898783          2               135                  16               0                4
Correlated subquery                              gdazhxm5xdu44       864898783          2               405                  16               0                4
Relational algebra method                        cx451qsx2qfcv      3901981856          2               426                  16               0                4
Scalar subquery in the SELECT clause             6y4kznqkvq635       750911849          2               701                  16               0                4
Uncorrelated subquery (double negative)          67azvy1nw1am1      2202369223          2              7702                 241               0                4
Correlated subquery (double negative)            ayvvv10ah456y       103534934          2             14499                 241               0                4
Scalar subquery in the WHERE clause              ddgmw1whng5ah      3607962630          2            195999               10549               0                4
Aggregate function to check existence            9df084bq799p1      3561519015          2            310690               10554               0                4

P.S. Automatic query rewrite is only available with Enterprise Edition. Users of Standard Edition can query the materialized view directly.

Day 8: Statistics are a double-edged sword

Day 10: Sometimes the optimizer needs a hint

About these ads
Categories: DBA, Oracle, SQL
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 668 other followers

%d bloggers like this: