Previous | Table of Contents | Next |
Again, it needs to be emphasized that table fragmentation does not cause performance problems. Rather, the row chaining that often accompanies table fragmentation will seriously impede performance. In fact, some Oracle DBAs have reported that extended tables (without row chaining) sometimes outperform tables that reside in a single extent. For detecting row chaining, see the next section.
Listing 7.7 shows a simple script can be run to see the number of times that a table has extended.
Listing 7.7 tblexts.sql lists all tables with more than 10 extents.
SET PAUSE OFF; SET ECHO OFF; SET LINESIZE 150; SET PAGESIZE 60; COLUMN c1 HEADING "Tablespace"; COLUMN c2 HEADING "Owner"; COLUMN c3 HEADING "Table"; COLUMN c4 HEADING "Size (KB)"; COLUMN c5 HEADING "Alloc. Ext"; COLUMN c6 HEADING "Max Ext"; COLUMN c7 HEADING "Init Ext (KB)"; COLUMN c8 HEADING "Next Ext (KB)"; COLUMN c9 HEADING "Pct Inc"; COLUMN c10 HEADING "Pct Free"; COLUMN c11 HEADING "Pct Used"; BREAK ON c1 SKIP 2 ON c2 SKIP 2 TTITLE "Fragmented Tables"; SELECT substr(seg.tablespace_name,1,10) c1, substr(tab.owner,1,10) c2, substr(tab.table_name,1,30) c3, seg.bytes/1024 c4, seg.extents c5, tab.max_extents c6, tab.initial_extent/1024 c7, tab.next_extent/1024 c8, tab.pct_increase c9, tab.pct_free c10, tab.pct_used c11 FROM sys.dba_segments seg, sys.dba_tables tab WHERE seg.tablespace_name = tab.tablespace_name AND seg.owner = tab.owner AND seg.segment_name = tab.table_name AND seg.extents > 10 ORDER BY 1,2,3;
Listing 7.8 shows the listing from this script.
Listing 7.8 The results from the tblexts.sql script.
SQL> @tblexts Thu Mar 14 page 1 Fragmented Tables Table Table Size Alloc Max Init Next Pct Pct Pct space Owner Ext (KB) Ext Ext Ext(KB) Ext(KB) Inc Free Used ------- ----- ----------- ----- ----- --- ------- ------- --- ---- ---- MPTV MPTVI UST_CAT 5800 58 249 100 100 0 20 40 SYSTEM SYS AUD$ 1724 11 249 12 840 50 10 40 CHAINED_ROWS 684 57 249 12 12 0 10 40 SOURCE$ 1724 11 249 12 840 50 10 40
Row fragmentation is one of the most problematic things that can happen to an Oracle system. This commonly occurs when an SQL UPDATE operation lacks sufficient room to expand the size of a row on its data block. When this happens, the row must extend onto the next available data block, causing an extra I/O when the row is accessed.
In Figure 7.7, the next five blocks are filled with rows. When an SQL update adds 1,500 bytes to row 1, the database chains to the next block. Finding no space, it chains to the next block, and the next block, before finding 1,500 bytes of free space on block 4. The fragment is stored in block 4, and a chain is established from the block header of block 1 to point to the next block header, and so on, until the fragment is located. Most databases have some type of free list at each block header to determine the total available space on each block.
Figure 7.7 An example of Oracle row chaining.
Any subsequent retrieval of row 1 will require the database to perform four physical block I/Os in order to retrieve the entire row. Since I/O time is usually the largest component of overall response time, this type of row fragmentation can greatly reduce performance.
Several preventative measures can be taken to avoid this situation. If the row will eventually contain all of its column values, and the values are of fixed length, the table could be defined with the parameter NOT NULL. This reserves space in the row when it is initially stored. If the row contains variable-length columns, then the PCTFREE parameter is increased to reserve space on each block for row expansion. By the way, this issue is not confined to Oracle. Most databases offer a utility that can be run periodically to check for row fragmentation. If fragments are found, the data must be exported to a flat file, the table redefined with different storage parameters, and the tables repopulated from a flat-file.
Listing 7.9 contains a script called chain.sql that will detect the number of chained rows for all Oracle tables. This script is a series of queries that acquire a list of all Oracle tables and write the ANALYZE TABLE syntax to an intermediate file, which is then executed to count the total number of chained rows for all tables. A chained row occurs when an SQL UPDATE operation has increased the size of a row, causing it to fragment onto another data block.
WARNING: Listing 7.9 creates table statistics that may force the use of the cost-based analyzer unless the database init.ora file parameter is set to RULE instead of CHOOSE.
Previous | Table of Contents | Next |