shrink a database in oracle 11g - oracle

I am not a database administrator by any means so I might be wrong in stating some of the things here.
In SQL Server, when we add a large amount of data in the database and then when we delete it, the size of the data files (.mdf file) or database (or whatever it is called) does not get reduced to the original size. We need to shrink it.
Do the same fundamentals work in Oracle? If yes then how should I go about shrinking an Oracle 11g database?

Full explanation from the Oracle Documentation: Reclaiming Wasted Space. For the short version:
"You can shrink space in a table, index-organized table, index,
partition, subpartition, materialized view, or materialized view log.
You do this using ALTER TABLE, ALTER INDEX, ALTER MATERIALIZED VIEW,
or ALTER MATERIALIZED VIEW LOG statement with the SHRINK SPACE
clause."
So, after running the Oracle Segment Advisor to recommend areas to shrink, something like the following will shrink space in a table named mytable.
SQL> alter table mytable enable row movement;
Table altered
SQL> alter table mytable shrink space;
Table altered

I have a similar case for a table size 28 Gb, when I deleted data from it, I saw no change occurred.
after I created another table from this table and dropped the first one, the size shrunk by 10 Gb to be 18Gb.
CREATE TABLE NEW_TBL AS SELECT * FROM OLD_TBL

Related

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

How to purge an Advanced Queue in Oracle

The documentation is clear about how to purge an Oracle AQ:
dbms_aqadm.purge_queue_table()
However, what happens to the storage, especially the high water marks of the queue table, the indexes and of the LOB segments? Is it necessary to shrink the table, too?
In production, the queues are nearly always empty (as they should), but in our test system, they fill up to millions of rows for various reasons, so they need to be emptied sometimes.
Is it neccessary to look at the underlying tables and indexes or is this taken care of automatically?
Many thanks!
DBMS_AQADM.PURGE_QUEUE_TABLE it is equivalent for truncate table. Also look at this error message when you try truncate queue table
ORA-24005: Inappropriate utilities used to perform DDL on AQ table %s.%s
*Cause: An attempt was made to use the SQL command DROP TABLE or TRUNCATE
TABLE or ALTER TABLE on queue metadata or tables.
*Action: Use the DBMS_AQADM.DROP_QUEUE_TABLE to DROP TABLE,
DBMS_AQADM.PURGE_QUEUE_TABLE to TRUNCATE TABLE.
ALTER TABLE redefinition based on only ALTER_TABLE_PROPERTIES and
ALTER_TABLE_PARTITIONING clauses are allowed.
Tom Kyte has already written info about often truncating table https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:47911859692542

How to shrink secure file LOBs in Oracle

I noticed today that SQL command that is used to shrink LOBs in oracle does not work in 12c.
ALTER TABLE SAMPLE_TABLE MODIFY lob (LOB_COLUMN) (SHRINK SPACE)
This returns oracle error
ORA-10635: Invalid segment or tablespace type
In the oracle documentation it is mentioned that the SHRINK option is not supported for SecureFiles LOBs.
I want to know how blob compresses in secure files. Does oracle handles that internally?
Thanks
ALTER TABLE SAMPLE_TABLE MOVE LOB(LOB_COLUMN) STORE AS (TABLESPACE USERS)
Note: this is, unlike how it can be read, a move lob operation. It is a move TABLE operation, and while at it, moving a lob too.
This is why it invalidates indexes, - because it moves the whole table not just the lob. And of course it can take a very long time and it will consume 2x space during the operation, because oracle makes a copy of the data and only after it's complete it frees the old segments.
If you want to shrink LOBs using SecureFiles, use this statement:
ALTER TABLE SAMPLE_TABLE MOVE LOB(LOB_COLUMN) STORE AS (TABLESPACE USERS)
Be careful using it - this command invalidates all indexes on SAMPLE_TABLE, so you should rebuild them after you're finished with LOBs:
ALTER INDEX <index_name> REBUILD;

Release unused space of USERS tablespace in oracle

I have lots of table with lots of records in oracle 11g. (more than 2 billions) After applying some queries and creating some indexes I am so close to insufficient disk space. Right now for executing each query ORA-01652 error for USERS tablespace appears. I cannot add more datafile to USERS tablespace anymore because of insufficient disk space. I am sure that there are lots of unused space available on this tablespace that is not usable somehow. (I deleted some tables and indexes nothing happened) My question is how can I release this space? Thank you very much.
I don't know if you can to it for an entire tablespace but for a single table the command is:
ALTER TABLE MY_TABLE ENABLE ROW MOVEMENT; -- By defaut ROW MOVEMENT is disabled when you create a table.
ALTER TABLE MY_TABLE SHRINK SPACE CASCADE;
ALTER TABLE MY_TABLE DEALLOCATE UNUSED;
Maybe you have to loop over ALL_TABLES in your schema.
Then you can gain disc space by rebuilding your indexes.
ALTER INDEX THE_INDEX REBUILD;

Is it safe to put an index on an Oracle Temporary Table?

I have read that one should not analyze a temp table, as it screws up the table statistics for others. What about an index? If I put an index on the table for the duration of my program, can other programs using the table be affected by that index?
Does an index affect my process, and all other processes using the table?
or Does it affect my process alone?
None of the responses have been authoritative, so I am offering said bribe.
Does an index effect my process, and all other processes using the table? or Does it effect my process alone?
I'm assuming we are talking of GLOBAL TEMPORARY tables.
Think of a temporary table as of multiple tables that are created and dropped by each process on the fly from a template stored in the system dictionary.
In Oracle, DML of a temporary table affects all processes, while data contained in the table will affect only one process that uses them.
Data in a temporary table is visible only inside the session scope. It uses TEMPORARY TABLESPACE to store both data and possible indexes.
DML for a temporary table (i. e. its layout, including column names and indexes) is visible to everybody with sufficient privileges.
This means that existence of the index will affect your process as well as other processes using the table in sense that any process that modifies data in the temporary table will also have to modify the index.
Data contained in the table (and in the index too), on the contrary, will affect only the process that created them, and will not even be visible to other processes.
IF you want one process to use the index and another one not to use it, do the following:
Create two temporary tables with same column layout
Index on one of them
Use indexed or non-indexed table depending on the process
I assume you're referring to true Oracle temporary tables and not just a regular table created temporarily and then dropped. Yes, it is safe to create indexes on the temp tables and they will be used according to the same rules as a regular tables and indexes.
[Edit]
I see you've refined your question, and here's a somewhat refined answer:
From:
Oracle® Database Administrator's Guide
10g Release 2 (10.2)
Part Number B14231-02
"Indexes can be created on temporary tables. They are also temporary and the data in the index has the same session or transaction scope as the data in the underlying table."
If you need the index for efficient processing during the scope of the transaction then I would imagine you'll have to explicitly hint it in the query because the statistics will show no rows for the table.
You're asking about two different things, indexes and statistics.
For indexes, yes, you can create indexes on the temp tables, they will be maintained as per usual.
For statistics, I recommend that you explicitly set the stats of the table to represent the average size of the table when queried. If you just let oracle gather stats by itself, the stats process isn't going to find anything in the tables (since by definition, the data in the table is local to your transaction), so it will return inaccurate results.
e.g. you can do:
exec dbms_stats.set_table_stats(user, 'my_temp_table', numrows=>10, numblks=>4)
Another tip is that if the size of the temporary table varies greatly, and within your transaction, you know how many rows are in the temp table, you can help out the optimizer by giving it that information. I find this helps out a lot if you are joining from the temp table to regular tables.
e.g., if you know the temp table has about 100 rows in it, you can:
SELECT /*+ CARDINALITY(my_temp_table 100) */ * FROM my_temp_table
Well, I tried it out and the index was visible and used by the second session. Creating a new global temporary table for your data would be safer if you really need an index.
You are also unable to create an index while any other session is accessing the table.
Here's the test case I ran:
--first session
create global temporary table index_test (val number(15))
on commit preserve rows;
create unique index idx_val on index_test(val);
--second session
insert into index_test select rownum from all_tables;
select * from index_test where val=1;
You can also use the dynamic sampling hint (10g):
select /*+ DYNAMIC_SAMPLING (3) */ val
from index_test
where val = 1;
See Ask Tom
You cannot create an index on a temporary table while it is used by another session, so answer is: No, it cannot affect any other process, because it is not possible.
An existing Index affects only your current session, because for any other session the temporary table appears empty, so it cannot access any index values.
Session 1:
SQL> create global temporary table index_test (val number(15)) on commit preserve rows;
Table created.
SQL> insert into index_test values (1);
1 row created.
SQL> commit;
Commit complete.
SQL>
Session 2 (while session 1 is still connected):
SQL> create unique index idx_val on index_test(val);
create unique index idx_val on index_test(val)
*
ERROR at line 1:
ORA-14452: attempt to create, alter or drop an index on temporary table already in use
SQL>
Back to session 1:
SQL> delete from index_test;
1 row deleted.
SQL> commit;
Commit complete.
SQL>
Session 2:
SQL> create unique index idx_val on index_test(val);
create unique index idx_val on index_test(val)
*
ERROR at line 1:
ORA-14452: attempt to create, alter or drop an index on temporary table already in use
SQL>
still failing, you first have to disconnect session 1 or table has to be truncated.
Session 1:
SQL> truncate table index_test;
Table truncated.
SQL>
Now you can create the index in Session 2:
SQL> create unique index idx_val on index_test(val);
Index created.
SQL>
This index of course will be used by any session.

Resources