• Aucun résultat trouvé

Should You Use NULLs?

Dans le document Oracle Essentials Oracle Database 11g (Page 110-118)

The idea of three-state logic may seem somewhat confusing, especially when you imag-ine your poor end users executing ad hoc queries and trying to account for a value that’s neither TRUE nor FALSE. This prospect may concern you, so you may decide not to use NULL values at all.

We believe that NULLs have an appropriate use. The NULL value covers a very spe-cific situation: a time when a column has not had a value assigned. The alternative to using a NULL is using a value with another meaning—such as 0 for numbers—and then trying to somehow determine whether that value has actually been assigned or simply exists as a replacement for NULL.

If you choose not to use NULL values, you’re forcing a value to be assigned to a column for every row. Youare, in effect, eliminating the possibility of having a column that doesn’t require a value, as well as potentially assigning misleading values for certain columns. This situation can be misleading for end users and can lead to inaccurate results for summary actions such as AVG (average).

Avoiding NULL values simply replaces one problem—educating users or providing them with an interface that implicitly understands NULL values—with another set of problems, which can lead to a loss of data integrity.

Basic Data Structures | 91 is read-only; youcannot update the data it contains. The external table is good for loading and unloading data to files from a database, among other purposes.

Oracle Database 11g introduces the ability to create virtual columns for a table.

These columns are defined by an expression and, although the results of the expres-sion are not stored, the columns can be accessed by applications at runtime.

Views

Aviewis an Oracle data structure defined through a SQL statement. The SQL state-ment is stored in the database. When you use a view in a query, the stored query is executed and the base table data is returned to the user. Views do not contain data, but represent ways to look at the base table data in the way the query specifies.

You can use a view for several purposes:

• To simplify access to data stored in multiple tables.

• To implement specific security for the data in a table (e.g., by creating a view that includes a WHERE clause that limits the data you can access through the view).

Starting with Oracle9i, youcan usefine-grained access controlto accomplish the same purpose. Fine-grained access control gives you the ability to automatically limit data access based on the value of data in a row.

• To isolate an application from the specific structure of the underlying tables.

A view is built on a collection ofbase tables, which can be either actual tables in an Oracle database or other views. If youmodify any of the base tables for a view so that they no longer can be used for a view, that view itself can no longer be used.

In general, you can write to the columns of only one underlying base table of a view in a single SQL statement. There are additional restrictions for INSERT, UPDATE, and DELETE operations, and there are certain SQL clauses that prevent you from updating any of the data in a view.

You can write to a nonupdateable view by using an INSTEAD OF trigger, which is described later in this chapter.

Oracle8iintroducedmaterialized views. These are not really views as defined in this section, but are physical tables that hold presummarized data providing significant performance improvements in a data warehouse. Materialized views are described in more detail in Chapter 10.

Indexes

Anindexis a data structure that speeds up access to particular rows in a database.

An index is associated with a particular table and contains the data from one or more columns in the table.

92 | Chapter 4: Oracle Data Structures

The basic SQL syntax for creating an index is shown in this example:

CREATE INDEX emp_idx1 ON emp (ename, job);

in whichemp_idx1is the name of the index,empis the table on which the index is cre-ated, andename andjob are the column values that make up the index.

The Oracle database server automatically modifies the values in the index when the values in the corresponding columns are modified. Because the index contains less data than the complete row in the table and because indexes are stored in a special structure that makes them faster to read, it takes fewer I/O operations to retrieve the data in them. Selecting rows based on an index value can be faster than selecting rows based on values in the table rows. In addition, most indexes are stored in sorted order (either ascending or descending, depending on the declaration made when you created the index). Because of this storage scheme, selecting rows based on a range of values or returning rows in sorted order is much faster when the range or sort order is contained in the presorted indexes.

In addition to the data for an index, an index entry stores the ROWID for its associ-ated row. The ROWID is the fastest way to retrieve any row in a database, so the subsequent retrieval of a database row is performed in the most optimal way.

An index can be either unique (which means that no two rows in the table or view can have the same index value) or nonunique. If the column or columns on which an index is based contain NULL values, the row isn’t included in an index.

An index in Oracle refers to the physical structure used within the database. Akeyis a term for a logical entity, typically the value stored within the index. In most places in the Oracle documentation, the two terms are used interchangeably, with the nota-ble exception of the foreign key constraint, which is discussed later in this chapter.

Four different types of index structures, which are described in the following sec-tions, are used in Oracle: standard B*-tree indexes; reverse key indexes; bitmap indexes; and function-based indexes, which were introduced in Oracle8i. Oracle Database 11gdelivers the ability to use invisible indexes, which are described below.

Oracle also gives youthe ability to cluster the data in the tables, which can improve performance. This is described later, in the section “Clusters.”

B*-tree indexes

TheB*-tree indexis the default index used in Oracle. It gets its name from its resem-blance to an inverted tree, as shown in Figure 4-1.

The B*-tree index is composed of one or more levels of branch blocks and a single level of leaf blocks. The branch blocks contain information about the range of values contained in the next level of branch blocks. The number of branch levels between the root and leaf blocks is called thedepthof the index. The leaf blocks contain the actual index values and the ROWID for the associated row.

Basic Data Structures | 93 The B*-tree index structure doesn’t contain many blocks at the higher levels of branch blocks, so it takes relatively few I/O operations to read quite far down the B*-tree index structure. All leaf blocks are at the same depth in the index, so all retrievals require essentially the same amount of I/O to get to the index entry, which evens out the performance of the index.

Oracle allows youto createindex organized tables (IOTs), in which the leaf blocks store the entire row of data rather than only the ROWID that points to the associ-ated row. Index organized tables reduce the total amount of space needed to store an index and a table by eliminating the need to store the ROWID in the leaf page. But index organized tables cannot use a UNIQUE constraint or be stored in a cluster. In addition, index organized tables don’t support distribution, replication, and parti-tioning (covered in greater detail in other chapters), although IOTs can be used with Oracle Streams for capturing and applying changes with Oracle Database 10g and later releases.

There were a number of enhancements to index organized tables as of Oracle9i, including a lifting of the restriction against the use of bitmap indexes as secondary indexes for an IOT and the ability to create, rebuild, or coalesce secondary indexes on an IOT. Oracle Database 10gcontinued this trend by allowing replication and all types of partitioning for index organized tables, as well as providing other enhancements.

94 | Chapter 4: Oracle Data Structures

Reverse key indexes

Reverse key indexes, as their name implies, automatically reverse the order of the bytes in the key value stored in the index. If the value in a row is “ABCD”, the value for the reverse key index for that row is “DCBA”.

To understand the need for a reverse key index, you have to review some basic facts about the standard B*-tree index. First and foremost, the depth of the B*-tree is deter-mined by the number of entries in the leaf nodes. The greater the depth of the B*-tree, the more levels of branch nodes there are and the more I/O is required to locate and access the appropriate leaf node.

The index illustrated in Figure 4-1 is a nice, well-behaved, alphabetic-based index.

It’s balanced, with an even distribution of entries across the width of the leaf pages.

But some values commonly used for an index are not so well behaved. Incremental values, such as ascending sequence numbers or increasingly later date values, are always added to the right side of the index, which is the home of higher and higher values. In addition, any deletions from the index have a tendency to be skewed toward the left side as older rows are deleted. The net effect of these practices is that over time the index turns into an unbalanced B*-tree, where the left side of the index is more sparsely populated than the leaf nodes on the right side. This unbalanced growth has the overall effect of having an unnecessarily deep B*-tree structure, with the left side of the tree more sparsely populated than the right side, where the new, larger values are stored. The effects described here also apply to the values that are automatically decremented, except that the left side of the B*-tree will end up hold-ing more entries.

Youcan solve this problem by periodically dropping and re-creating the index. How-ever, you can also solve it by using the reverse value index, which reverses the order of the value of the index. This reversal causes the index entries to be more evenly dis-tributed over the width of the leaf nodes. For example, rather than having the values 234, 235, and 236 be added to the maximum side of the index, they are translated to the values 432, 532, and 632 for storage and then translated back when the values are retrieved. These values are more evenly spread throughout the leaf nodes.

The overall result of the reverse index is to correct the imbalance caused by continu-ally adding increasing values to a standard B*-tree index. For more information about reverse key indexes and where to use them, refer to your Oracle documentation.

Bitmap indexes

In a standard B*-tree index, the ROWIDs are stored in the leaf blocks of the index. In abitmap index, each bit in the index represents a ROWID. If a particular row con-tains a particular value, the bit for that row is “turned on” in the bitmap for that value. A mapping function converts the bit into its corresponding ROWID. Unlike other index types, bitmap indexes include entries for NULL values.

Basic Data Structures | 95 Youcan store a bitmap index in much less space than a standard B*-tree index if there aren’t many values in the index. Figure 4-2 shows an illustration of how a bit-map index is stored. Figure 10-3 in Chapter 10 shows how a bitbit-map index is used in a selection condition.

The functionality provided by bitmap indexes is especially important in data ware-housing applications in which each dimension of the warehouse contains many repeating values, and queries typically require the interaction of several different dimensions. For more about data warehousing, see Chapter 10.

Function-based indexes

Function-based indexeswere introduced in Oracle8i. A function-based index is just like a standard B*-tree or bitmap index, except that youcan base the index on the result of a SQL function, rather than just on the value of a column or columns.

Prior to Oracle8i, if you wanted to select on the result of a function, Oracle retrieved every row in the database, executed the function, and then accepted or rejected each row. With function-based indexes you can simply use the index for selection, with-out having to execute the function on every row, every time.

For example, without a function-based index, if you wanted to perform a case-insensitive selection of data you would have to use the UPPER function in the WHERE clause, which would retrieve every candidate row and execute the func-tion. With a function-based index based on the UPPER function, you can select directly from the index.

96 | Chapter 4: Oracle Data Structures

As of Oracle Database 10g, youcan perform case- or accent-insensitive queries; these queries provide another way to solve this problem.

This capability becomes even more valuable when you consider that you can create your own functions in an Oracle database. You can create a very sophisticated func-tion and then create an index based on the funcfunc-tion, which can dramatically affect the performance of queries that require the function.

Invisible indexes

Oracle Database 11g introduces a new option for all of the index types we’ve dis-cussed in previous sections—the invisible index. Normally, all indexes are used by the optimizer, which is described later in this chapter. Youcan eliminate an index from optimizer consideration by taking the index offline or by deleting the index. But with both of these methods youwill have to take some actions to bring the index up to date when you bring it back into the database environment.

But what if you want to just remove the index from optimizer consideration for a limited time, such as when you are testing performance? With the invisible option, an index is not considered as a possible step in an access path, but updates and deletes to the underlying data are still applied to the index.

Partitioning

With the Enterprise Editions of Oracle8 and beyond, youcan purchase the Partition-ing Option. As the name implies, this option allows youto partition tables and indexes. Partitioning a data structure means that you can divide the information in the structure among multiple physical storage areas. A partitioned data structure is divided based on column values in the table. You can partition tables based on the range of column values in the table (often date ranges), or as the result of a hash function (which returns a value based on a calculation performed on the values in one or more columns). As of Oracle9iyou can also use a list of values to define a par-tition, which can be particularly useful in a data warehouse environment. Oracle Database 11gaddsinterval partitioning, providing the ability to automatically gener-ate a new partition of a fixed interval or range when data to be inserted does not fit into existing partition ranges.

Youcan also have two levels of partitions, calledcomposite partitions, using a combi-nation of partition methods. Prior to Oracle Database 11g, you could partition using a composite of range and hash partitioning. Oracle Database 11gadds the ability to combine list partitioning with list, range, or hash partitioning, or range partitioning with a different range partitioning scheme.

Basic Data Structures | 97 Oracle is smart enough to take advantage of partitions to improve performance in two ways:

• Oracle won’t bother to access partitions that won’t contain any data to satisfy the query.

• If all the data in a partition satisfies a part of the WHERE clause for the query, Oracle simply selects all the rows for the partition without bothering to evaluate the clause for each row.

Partitioned tables are especially useful in a data warehouse, in which data can be par-titioned based on the time period it spans.

Equally important is the fact that partitioning substantially reduces the scope of maintenance operations and increases the availability of your data. You can perform all maintenance operations, such as backup, recovery, and loading, on a single parti-tion. This flexibility makes it possible to handle extremely large data structures while still performing those maintenance operations in a reasonable amount of time. In addition, if youmust recover one partition in a table for some reason, the other parti-tions in the table can remain online during the recovery operation.

If youhave been working with other databases that don’t offer the same type of par-titioning, youmay have tried to implement a similar functionality by dividing a table into several separate tables and then using a UNION SQL command to view the data in several tables at once. Partitioned tables give youall the advantages of having sev-eral identical tables joined by a UNION command without the complexity that implementation requires.

To maximize the benefits of partitioning, it sometimes makes sense to partition a table and an index identically so that both the table partition and the index partition map to the same set of rows. Youcan automatically implement this type of partition-ing, which is calledequipartitioning, by specifying an index for a partitioned table as a LOCAL index. Local indexes simplify maintenance, since standard operations, such as dropping a partition, will work transparently with both the index partition and the table partition.

Oracle has continued to increase the functionality of partitioning features. Since Ora-cle Database 10gRelease 2, youcan reorganize individual partitions online, the max-imum number of partitions increased from 64 KB – 1 to 128 KB – 1, and query optimization using partition pruning improved.

Oracle Database 11gfurther improves partition pruning, enables applications to con-trol partitioning, and adds a Partition Advisor that can help youto understand when partitioning might improve the performance of your Oracle database.

For more details about the structure and limitations associated with partitioned tables, refer to your Oracle documentation.

98 | Chapter 4: Oracle Data Structures

Dans le document Oracle Essentials Oracle Database 11g (Page 110-118)