Primary Keys


We start with the simplest, yet most common where clause: the primary key lookup. For that purpose, we create the EMPLOYEES table, which is used for all examples in this chapter:

CREATE TABLE employees (
   employee_id   NUMBER         NOT NULL,
   first_name    VARCHAR2(1000) NOT NULL,
   last_name     VARCHAR2(1000) NOT NULL,
   date_of_birth DATE           NOT NULL,
   phone_number  VARCHAR2(1000) NOT NULL,
   CONSTRAINT employees_pk PRIMARY KEY (employee_id)
);

The database creates an index for the primary key automatically. That means, there is an index on EMPLOYEE_ID, even though there is no create index statement.

Tip

Appendix C, “Example Schema” contains scripts to populate the EMPLOYEES table with sample data. You can use it to test the examples in your own environment.

To follow the text, it is enough to know that the table contains 1000 rows.

The following query uses the primary key to retrieve an employee’s name:

SELECT first_name, last_name 
  FROM employees 
 WHERE employee_id = 123

A query on the primary key cannot deliver multiple rows. It is therefore sufficient to traverse the index tree without following the leaf nodes. The so-called execution plan can be used to verify the thesis:

---------------------------------------------------------------
|Id |Operation                   | Name         | Rows | Cost |
---------------------------------------------------------------
| 0 |SELECT STATEMENT            |              |    1 |    2 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES    |    1 |    2 |
|*2 |  INDEX UNIQUE SCAN         | EMPLOYEES_PK |    1 |    1 |
---------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("EMPLOYEE_ID"=123)

The Oracle execution plan shows an INDEX UNIQUE SCAN—the operation that performs the tree traversal only. It takes the best benefit from the logarithmic scalability and retrieves the entry almost instantly.

Tip

The execution plan (sometimes explain plan or query plan) shows the steps the database takes to execute the statement. Appendix A, “Execution Plans” explains how to retrieve an execution plan from different databases and contains a short reference of the most common operations.

The database performs an additional step, the TABLE ACCESS BY INDEX ROWID, to fetch the actual table data (FIRST_NAME, LAST_NAME). This operation can become a performance bottleneck—as explained in “Slow Indexes, Part I”—but is no risk for an INDEX UNIQUE SCAN. A unique scan delivers one entry only so that the table access is limited to one access as well. That means, the ingredients for a slow query cannot occur with an INDEX ONLY SCAN.

Primary Keys Supported by Nonunique Indexes

Nonunique indexes can be used to support a primary key or unique constraint. In that case the lookup requires an INDEX RANGE SCAN instead of an INDEX UNIQUE SCAN. The constraint still maintains the uniqueness of every key so that the performance impact is often negligible. In case the searched key is the last in its leaf node, the next leaf node will be read to see if there are more matching entries. The example in “The B-Tree: Makes the Index Fast” explains this phenomenon.

Using nonunique index to enforce a primary key allows to define the constraint deferrable. While regular constraints are validated during statement execution the validation of a deferrable constraint is postponed until the transaction is committed. Deferred constraints are required to propagate data into tables with circular foreign key dependencies.

Coaching by the Author
Faster, easier and more memorable than reading.

Recent Questions at Ask.Use-The-Index-Luke.com

0
votes
1
answer
229
views

query regd the CBO decision

Apr 17 at 10:27 Hulda(suspended)
index-choice optimizer
0
votes
3
answers
2.0k
views

Examples for Function Based Indexes?

Mar 25 at 15:52 Castorp 1
function-based
0
votes
1
answer
610
views

Updating multiple rows using a subquery in SQL

Jan 08 at 09:52 Jan 26
subquery update sql