Currently by default create table and index DDLs will place tables in MYDB_DATA_TABLE_SPACE, I would like to specify a different default table space for indexes from table data so that I do not have to always explicitly mention that in my create index DDL. Is this possible?
Current:
Table -> MYDB_DATA_TABLE_SPACE
Required:
Table -> MYDB_DATA_TABLE_SPACE
Index -> MYDB_INDX_TABLE_SPACE
You can't specify a different default tablespace for indexes and for tables. Each user only gets one default tablespace.
Hopefully, you're not trying to maintain separate tablespaces for performance reasons. There is a relatively common myth that you can improve performance by storing data and indexes in separate tablespaces. I'm personally not a big fan of putting indexes and data in different tablespaces-- there are no performance differences, it is terribly unlikely that you could run the application without the index tablespace so there aren't any recoverability benefits. I understand that it can appeal to some folks sense of organization so I don't object categorically.
Sorry, there is no way to do that.
A default tablespace may be set per user, but it applies to all segment creation: tables, indexes, materialized views, etc.
Hope that helps.
Related
While creating tables or indexes, I always get the recommendation to add tablespace clause in the queries. Is there any major impact later on our table if we don't use the tablespace clause while creating them ?
This is what I am doing for a very long time.
CREATE TABLE XT_PMB_NOTIFY_UNSUB(
TXNID NUMBER(15),
APP_SEQNO NUMBER(15),
PRIMARY_KEYVAL VARCHAR2(4000) NOT NULL,
OP_CODE VARCHAR2(15),
TXN_STATUS VARCHAR2(1),
CREATE_DT DATE,
PRIMARY KEY (TXNID) );
Recommendation from DBA.
CREATE TABLE XT_PMB_NOTIFY_UNSUB(
TXNID NUMBER(15),
APP_SEQNO NUMBER(15),
PRIMARY_KEYVAL VARCHAR2(4000) NOT NULL,
OP_CODE VARCHAR2(15),
TXN_STATUS VARCHAR2(1),
CREATE_DT DATE,
PRIMARY KEY (TXNID) )
TABLESPACE DATA_ENC_TS;
The answer is it depends on how your company has defined its tablespace rules.
Oracle users (or schemas) can have one "default tablespace" which you can see by querying the database:
select username, default_tablespace from dba_users;
or if you do not have permission for that and you want to know what it is for the current user only:
select username, default_tablespace from user_users;
Or perhaps this one to see all users that are visible to your current connected user:
select username, default_tablespace from user_users;
According to Oracle documentation (https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_8003.htm) this is what it means:
Specify the default tablespace for objects that the user creates. If
you omit this clause, then the user's objects are stored in the
database default tablespace. If no default tablespace has been
specified for the database, then the user's objects are stored in the
SYSTEM tablespace.
So for your intents and purposes, when you create a table without explicitly using a tablespace at the end it will go to the user's default tablespace in general. If your DBAs tend to not define a default tablespace then it starts to have more serious impacts, because the table will be stored in a global default tablespace or (heaven forbid) it will go to SYSTEM tablespace. That last option would be extremely detrimental to the database health.
Some companies have the habit of assigning different tablespaces for tables and for indexes for instance. In that case, the users can only have one default tablespace, and if you omit the tablespace clause in the create index (or create table) statement, objects will go to the incorrect tablespace.
Now to the consequences of having a table or index in an incorrect tablespace. A tablespace is a collection of one or more physical operating system files (Oracle refers to them as data files). Whenever you create a table or index in a tablespace oracle allocates space in that datafile, which Oracle calls segments. Segments are logical units inside a data file. Keep in mind Oracle further breaks down segments into smaller logical units called extents and blocks, but that is a bit beyond the topic here. If you are interested there is more to read here: https://docs.oracle.com/cd/B19306_01/server.102/b14220/logical.htm
Let's go back to segments. Segments exist inside datafiles that belong to tablespaces. When you put your object in a tablespace and you want to move it out to a different tablespace, Oracle needs to physically write to files on the OS. And that can be simple if the table is empty, or can be a fair amount of work if it concerns a massive table spanning multiple datafiles or containing gigabytes or terabytes of data. It may mean an application outage is required to fix it.
Oracle provides certain methods to avoid application outages in those scenarios, like for example Online Redefinition (package DBMS_REDEFINITION). But I would hope we can agree that their use can be better leveraged for application migrations and things of the sort.
Using default tablespace settings is fine in many cases, by all means, but if you will allow me perhaps, the rule of thumb for many things Oracle is if you can write code to do something explicitly instead of relying on default values, do yourself and your DBA the favor. In general, the flexibility of relying on it is trumped by even a couple times of facing yourself with a surprise and then being responsible for cleaning it up later.
If you don't specify a tablespace, Oracle will use the default tablespaces assigned to the schema. You can find your default tablespace with the query below. Unless you have a very small development database w/o many schemas, that may be OK, but otherwise it is good practice to explicitly define them.
select *
from database_properties
where property_name like 'DEFAULT%TABLESPACE';
PROPERTY_NAME PROPERTY_VALUE DESCRIPTION
------------------------------ -------------------- ----------------------------------------
DEFAULT_TEMP_TABLESPACE TEMP Name of default temporary tablespace
DEFAULT_PERMANENT_TABLESPACE USERS Name of default permanent tablespace
I would like to use the power of bitmap indexes for tables where the indexed column has lots of repeating values, however I am in an OLTP environment. The rule is that you must not use bitmap indexes in an OLTP environment, since it causes block level locking when rows in the table are updated. I definitely do not want block level locking.
My table is however very static, that is it is very unlikely that a row will be added to it. Also two people would not add rows at the same time, so locking for that table is not that important.
My concern however is whether the locking on the table with the bitmap indexes could cause locking on other tables if the table is used in DML, DDL or sql statements along with other tables.
So is it safe to use a bitmap index in this scenario and can it cause locking in tables other than the table with the bitmap index.
For example:
Table per_person_types:
person_type_id description internal_name
1 Contractor EMP
2 Employee EMP
3 Terminated TERM
where I want the bitmap index on internal_name.
Yes, it's safe to use a bitmap index here.
The rule is per table, not per environment. It doesn't matter how volatile the database is, as long as the relevant table is static then bitmap indexes won't cause locking issues.
From the manual, part of the conditions for using a bitmap index are:
The indexed table is either read-only or not subject to significant
modification by DML statements.
Oracle stores lock information with the data. It does not track all locks in a global table. Locking unrelated objects will generally not cause too many locks, lock escalation, or other problems.
Also, bitmap indexes don't specifically lock per-block. The bitmaps can be compressed, and updating a single row can potentially lock the entire table.
If you're still nervous about bitmap indexes you could try using btree index compression instead. For highly repetitive values it can significantly shrink the size of the index, making it faster for some operations.
I have an Oracle table that is in it's own tablespace. It has a spatial index in another tablespace and a normal index in another. If I want to drop them all. Does it matter what order I proceed in?
Drop the table. The indexes will be dropped along with the table.
Indexes are optional structures associated with tables and clusters. If you drop the table, the associated indexes are also dropped.
To answer your confusion about different tablespaces, there is a reason to create in different tablespace or within same tablespace as that of the table. Keeping them in same tablespace makes it easy for database maintenance, however, keeping in different tablespaces is better in terms of performance.
From documentation -
Indexes can be created in any tablespace. An index can be created in
the same or different tablespace as the table it indexes. If you use
the same tablespace for a table and its index, it can be more
convenient to perform database maintenance (such as tablespace or file
backup) or to ensure application availability. All the related data is
always online together.
Using different tablespaces (on different disks) for a table and its
index produces better performance than storing the table and index in
the same tablespace. Disk contention is reduced. But, if you use
different tablespaces for a table and its index and one tablespace is
offline (containing either data or index), then the statements
referencing that table are not guaranteed to work.
We are running Oracle 11g and have some partitioned tables. I am trying to write an automated process to script out the indexes on these tables. (Basically when we do bulk loads, we want to drop all the indexes beforehand and recreate them afterward.)
The problem I have is knowing how to script out the partitioned indexes. Some are created with "LOCAL STORE IN (tablespacename)" and others just with "LOCAL" (which stores index extents in the same partition as the data). In either case, dba_indexes.tablespace_name is null, and I have having a heck of a time scripting out the two different cases correctly.
I know I can simply re-run the original DDL to recreate the indexes, but multiple parts of the organization can make changes, and there would be less risk if the loader tool could be self-contained and simply rebuild whatever was there to begin with.
I can query dba_ind_subpartitions, and if the tablespace_name values for every subpartition all match, then I can assume/infer that I should STORE IN that tablespace name. But, if the table is in a small single-partition state (e.g. newly created or just after archival), then the ones created with just LOCAL also match this test, so this is also not a perfect way of telling them apart.
I can compare the names of the index subpartition tablespaces to the data table partition tablespaces, and if they match, then I can assume/infer that those should be created with just LOCAL. But, that drags a bunch of extra tables into my query and makes it really hard to read, so I am worried about maintainability going forward. Plus, it just seems like a kludge.
It seems like there should be someplace in Oracle's data dictionaries where it is simply keeping track of this, and where I can just directly look it up instead of having to do a bunch of math and rely on assumptions. But, I have done a good deal of digging and haven't yet found it. So, any help would be much appreciated.
Although an insert alone is faster without the presence of indexes, have you benchmarked a load into tables with indexes enabled and established that it is slower than disabling (more robust than dropping!) and rebuilding them?
When you direct path insert into a table with indexes, Oracle optimises the index maintenance process by creating temporary segments to hold just the data required for the index builds. This generally allows the index maintenance to scan much smaller segments than otherwise required -- the temp segments plus the existing indexes.
Well, as jonearles describes, the dbms_metadata package is the way to generate DDL for existing objects.
But, it seems to me, this is more work than is required for what you're trying to achieve. If this is all for loading data, I recommend you simply alter the indexes to be unusable, set 'skip_unusable_indexes=true', do the data load, and the rebuild the indexes.
This should achieve what you want, without having to drop and re-create the indexes.
DBMS_METADATA.GET_DDL is easier than querying the data dictionary:
--Sample table and index.
create table test1(a number);
create index test1_idx on test1(a);
--Store the DDL, drop the index, then re-create it.
declare
ddl_before clob;
begin
ddl_before := dbms_metadata.get_ddl('INDEX', 'TEST1_IDX');
execute immediate 'drop index test1_idx';
--Do some processing here.
execute immediate ddl_before;
end;
/
My question regards the situation were tablespace used for primary key index differs from tablespace used for the table itself. Will Oracle use this index or it becomes unusable?
Because when i tried to import the schema to Oracle that contains that table. Oracle complained with warning saying that index for this primary key is unusable. I've fixed the schema by change tablespace for primary key index, exported it again and it imported into database without warnings.
Does this means that primary key index tablespace must be always the same as the tablespace of the table itself? Or is it true for any kind of index (column index for example)?
Does this rule apply also for DB2?
Storing indexes and data in different tablespaces is perfectly acceptable. What happens when you do a:
alter index index_name rebuild;
Is the index still unusable after that? If not, check your import parameters on the table. For example, SQL*Loader can invalidate indexes with direct path loads (this is just a guess, you don't mention how you loaded the data).
If the index is still unusable, check for data anomalies, especially duplicate keys. Hope you fix it!
What Martin said is fine. However, there is no real need to separate the tablespaces. What you can do, to avoid tablespace errors on import (assuming you're using export/import and not datapump) is to create the user with a default tablespace that exists. Then import just the database and then add the indexes and constraints.