How To Rebuild Index of a specific table in Oracle? - oracle

I am wondering how to rebuild an index of specific table.
SELECT 'ALTER INDEX '||OWNER||'.'||INDEX_NAME||' REBUILD;'
FROM DBA_INDEXES
WHERE TABLE_NAME = 'JR_SETTING_D';
After running this code, I have tried to insert values in the table but it keeps telling me that
ORA-01502: index or partition of such index is in usable state tips
I am looking for any way of simply rebuilding the table's indexes that I have mentioned in the where statement of the query.

If index (or its partition) is in unusable state and rebuild doesn't help, I'd suggest you to drop the index, insert data (will be faster as Oracle won't have to maintain the index during insert) and - once you're done - create the index again.

Related

Oracle How to make insert faster

I have a table with 100 million rows and I want to make inserts to this table faster. Unfortunatelly, I cant use insert with APPEND hint, because locking table is forbidden.
Table has two indexes, so, will inserts be faster if i try to rebuild index or coalesce? Or maybe I should SHRINK this table ?
And will coalesce or rebuild index online lock this table?

Bulk update in Oracle12c

I have a situation like to update a column(all rows) in a table having 150 million records.
Creation of duplicate table with updates and dropping of previous table is the best way but there is no available disk space to hold the duplicate table.
So how to perform the update in less time? Partitions are there on the table.
I am using oracle 12c
The cleanest approach is NOT updating the table, but creating a new table with the new column of updated rows. For instance, let's say I needed to update a column called old_value with the max of some value, instead of updating the old_table one does:
create new_table as select foo, bar, max(old_value) from old_table;
drop table old_table;
rename new_table as old_table.
If you need even more speed, you can do this creation using a parallel query with nologging thereby generating very little redo and no undo logs. More details can be ascertained here: https://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:6407993912330

Oracle how to delete from a table except few partitions data

I have a big table with lot of data partitioned into multiple partitions. I want to keep a few partitions as they are but delete the rest of the data from the table. I tried searching for a similar question and couldn't find it in stackoverflow. What is the best way to write a query in Oracle to achieve the same?
It is easy to delete data from a specific partition: this statement clears down all the data for February 2012:
delete from t23 partition (feb2012);
A quicker method is to truncate the partition:
alter table t23 truncate partition feb2012;
There are two potential snags here:
Oracle won't let us truncate partitions if we have foreign keys referencing the table.
The operation invalidates any partitioned Indexes so we need to rebuild them afterwards.
Also, it's DDL, so no rollback.
If we never again want to store data for that month we can drop the partition:
alter table t23 drop partition feb2012;
The problem arises when we want to zap multiple partitions and we don't fancy all that typing. We cannot parameterise the partition name, because it's an object name not a variable (no quotes). So leave only dynamic SQL.
As you want to remove most of the data but retain the partition structure truncating the partitions is the best option. Remember to invalidate any integrity constraints (and to reinstate them afterwards).
declare
stmt varchar2(32767);
begin
for lrec in ( select partition_name
from user_tab_partitions
where table_name = 'T23'
and partition_name like '%2012'
)
loop
stmt := 'alter table t23 truncate partition '
|| lrec.partition_name
;
dbms_output.put_line(stmt);
execute immediate stmt;
end loop;
end;
/
You should definitely run the loop first with execute immediate call commented out, so you can see which partitions your WHERE clause is selecting. Obviously you have a back-up and can recover data you didn't mean to remove. But the quickest way to undertake a restore is not to need one.
Afterwards run this query to see which partitions you should rebuild:
select ip.index_name, ip.partition_name, ip.status
from user_indexes i
join user_ind_partitions ip
on ip.index_name = i.index_name
where i.table_name = 'T23'
and ip.status = 'UNUSABLE';
You can automate the rebuild statements in a similar fashion.
" I am thinking of copying the data of partitions I need into a temp
table and truncate the original table and copy back the data from temp
table to original table. "
That's another way of doing things. With exchange partition it might be quite quick. It might also be slower. It also depends on things like foreign keys and indexes, and the ratio of zapped partitions to retained ones. If performance is important and/or you need to undertake this operation regularly then you should to benchmark the various options and see what works best for you.
You must very be careful in drop partition from a partition table. Partition table usually used for big data tables and if (and only if) you have a global index on the table, drop partition make your global index invalid and you should rebuild your global index in a big table, this is disaster.
For minimum side effect for queries on the table in this scenario, I first delete records in the partition and make it empty partition, then with
ALTER TABLE table_name DROP PARTITION partition_name UPDATE GLOBAL INDEXES;
drop empty partition without make my global index invalid.

Oracle database, converting unique index to non-unique one

I understand I can't do this straightforward from studying similar questions on stackoverflow and other sites.
However, I need to do this and I'm willing to go with workarounds.
I tried to create a non-unique index with online and parallel, and then drop the old unique index. However, it fails saying ORA-01408: such column list already indexed.
How to convert an unique index to a non-unique one?
If you don't want to drop the old index before creating the new one, you can cheat a bit by creating the new index with an additional useless column, e.g.:
Assuming a table with the following configuration:
create table mytable (id number);
create unique index myunique on mytable (id);
To convert the index to non unique:
create index temp on mytable (id, 1);
drop index myunique;
create index mynonunique on mytable (id);
drop index temp;
In practice I'm not sure how necessary this is - generally I'd just drop and recreate the index in some low-activity period, preferably take the application down.
Oracle now supports multiple indexes applied to the same set of columns as long as they differ in uniqueness (and/or in some other properties such as bitmap vs. btree and partitioning) and
as long as only one of them is visible.
Therefore you can alter the existing index - changing it to invisible without dropping it and then create a new non-unique index.
CREATE TABLE mytable (id NUMBER);
CREATE UNIQUE INDEX mytable_unique_idx ON mytable(id);
ALTER INDEX mytable_unique_idx INVISIBLE;
CREATE INDEX mytable_nonunique_idx ON mytable(id);
Note that invisible indexes are still maintained by the database and you can change between them by turning one of them to invisible and the second one to visible.

How to make index unusable and then rebuilt in index

I have one function that insert thousands of records into table I want to unusable index at that time and then I am processing on that data data so I want to rebuilt that index again.
Is it possible in Oracle?
alter index idx_name unusable;
alter index idx_name rebuild;
but it is possible that you'll need:
drop index idx_name
create [unique] index idx_name ...

Resources