It is recommended, to put the indexes of all tables on a different tablespace than the data. For best performance on select-statements, it should be on a different disk (and a different controller), so that the database can check the index on disk1 while getting the data on disk2. You can easily change the index-tablespaces using the 'alter index' command. But first, let's have some thoughts about storage parameters!
| Storage parameters for indexes and tables |
A lot of databases are using standard parameters for the storage clause. The most important storage parameters are minextents, maxextents, initial, next and pct_increase. So what does it mean?
| initial | ...is the first size in bytes, which the database will reserve on space in the tablespace after the creation of the table. It's unnecessary to say, that you only can change this parameter during the 'create table statement', so you can forget this parameter, if you have already data in your tables. You can tenporary save this table, drop and recreate it to change this value. But it's not too bad, if you left the parameter to default. |
| next | ...is the size in bytes, which the database will take for the next extent of the table, when the initial size has been too small. So when your initial size is 100k and the table grows to bigger than 100k, an extension of the table is performed. The 'next' parameter is dependend of the 'pctincrease' parameter. |
| pctincrease | This parameter tells the database, how to choose the next extent. If this parameter has value 50, which is often the default, and the database has to perform an extent, it chooses 150% of the last or the initial extent. That means an exponential growth of needed data and index space in case of having big tables with lots of data. For example, if you have an initial size of 100k and pct_increase on value 50, for the sixteenth extent the database needs more than 10 MB and for the 22nd extent more than 100 MB, even if you need just one byte more! For my databases, I put this parameter to 0 for all tables and indexes and calculate the growth of the tables by myself. If you have a table with maybe 10 MB's a year growing size, you can put the parameters to initial 10M , next 10M and pct_increase 0. |
| maxextents | If you put pct_increase to 0, you have to be careful to set the value for maxextents, because the default is, having 2k block_size, 121. So a table with initial and next 100 k and max_extents 121 can only grow up to 121*100k what is about 12 MB. If the table once will need more space, you will get an error message, like unable to extent table .... I put this parameter to 'unlimited' because I don't want to be affected by this error-message and check the free space in my tablespaces once in a while. You have to think about this, if you but the maxextents parameter to unlimited! |
| minextents | ...tells you, how many extents are perofromed in one step. The default is 1 and nobody could tell me, why to change this value. |
| Changing the storage for tables |
So what to do now is changing the storage parameters of all tables. For example, we change all small tables to next 100k and pctincrease 0 , all medium tables (which already have the next extent higher than 1 MB) to next 1 MB and pctincrease 0 and all big tables to next 10MB and pctincrease 0. Modify the following script that it'll fit your system. Then run the script with SQL-Plus.
Script MAKE_STORAGE.SQL
SET FEEDBACK OFF SET HEADING OFF SET TERMOUT OFF SET LINESIZE 200 SPOOL ALTER_TABLE_STORAGES.SQL select 'alter table '||table_name||' storage '|| '(NEXT 100k pctincrease 0 maxextents unlimited minextents 1);' from user_tables where next_extent <= 100*1024; select 'alter table '||table_name||' storage '|| '(NEXT 1M pctincrease 0 maxextents unlimited minextents 1); ' from user_tables where next_extent < 10*1024*1024 and next_extent > 100*1024 ; select 'alter table '||table_name||' storage '|| '(NEXT 10M pctincrease 0 maxextents unlimited minextents 1);' from user_tables where next_extent >= 10*1024*1024; SPOOL OFF; SET FEEDBACK ON SET HEADING ON SET TERMOUT ON @ALTER_TABLE_STORAGES
| Rebuilding the indexes |
After having changed the storage parameters of all tables, we now can create a new tablespace on a different disk than the data tablespace and rebuild all indexes with the right storage parameters.
So first, let's create a new tablespace wit size 100 MB and give the tablespace the default storage parameters.
Create tablespace INDX datafile='C:\DATABASE\ORCL\indx.ora' size 100M storage (initial 100k next 100k maxextents unlimited minextents 1 pctincrease 0);
So all new crated indexes will get these storage parameters. If you want the same parameters as default for the data you can modify the data tablespace using
alter tablespace DATA storage (initial 100k next 100k minextents 1 maxextents unlimited pctincrease 0);
Having created a new tablespace called INDX, we no can rebuild all indexes to use that tablespace and new storage parameters. We do the same thing as we did for the tables, small indexes will get 100k, medium 1 MB and big ones 10 MB as next extent.
Script MAKE_INDEX_REBUILD.SQL
SET FEEDBACK OFF SET HEADING OFF SET TERMOUT OFF SET LINESIZE 200 SPOOL ALTER_INDEX_STORAGES.SQL select 'alter index '||index_name||' rebuild storage '|| '(INITIAL 100k NEXT 100k pctincrease 0 maxextents unlimited minextents 1)'|| 'tablespace INDX;' from user_indexes where next_extent <= 100*1024; select 'alter index '||index_name||' rebuild storage '|| '(INITIAL 1M NEXT 1M pctincrease 0 maxextents unlimited minextents 1)'|| 'tablespace INDX;' from user_indexes where next_extent < 10*1024*1024 and next_extent > 100*1024 ; select 'alter index '||index_name||' rebuild storage '|| '(INITIAL 10M NEXT 10M pctincrease 0 maxextents unlimited minextents 1)'|| 'tablespace INDX;' from user_indexes where next_extent > 10*1024*1024 ; SPOOL OFF; SET FEEDBACK ON SET HEADING ON SET TERMOUT ON @ALTER_INDEX_STORAGES
If you have tables or indexes which doesn't fit in th 100k, 1MB, 10MB size, you can easily change the storage parameter using the syntax in the created files ALTER_TABLE_STORAGES and ALTER_INDEX_STORAGES.
| Analyzing the schema |
For best performance, we now have to analyze tables and indexes to let the optimizer work properly. In the following script, you can exchange 'compute' with 'estimate' if you have really big tables. The script will, depending on how much data is in the tables, run several minutes. If you use 'compute', it runs longer.
The script only makes sense, if you have data in your tables. If you have a lot of traffic in your db, you should start the script once a week (or day).
Script ANALYZE.SQL
SET FEEDBACK OFF
SET HEADING OFF
SET TERMOUT OFF
SET LINESIZE 200
SPOOL ANALYZE_SCHEMA.SQL
select 'analyze table '||table_name||' compute statistics'||
' for all indexed columns;
' from user_tables;
select 'analyze table '||table_name||' compute statistics;
' from user_tables;
SPOOL OFF;
SET FEEDBACK ON
SET HEADING ON
SET TERMOUT ON
@ANALYZE_SCHEMA
You can use the utility dbms_utility.analyze_schema('SCHEMA_NAME','COMPUTE')
as well as the script but due to an Oracle8 - bug, the statistics for the indexes
might not be filled properly.