Consider following tables:
CREATE TABLE TAB_ONE
(
<irrelevant columns>
MESSAGE CLOB,
REC_DATE DATE,
<irrelevant columns>
) TABLESPACE DATA_TS;
and
CREATE TABLE TAB_TWO
(
<irrelevant columns>
RESPONSE CLOB,
PART_ID NUMBER,
<irrelevant columns>
CONSTRAINT "FK_01"
FOREIGN KEY ("PART_ID") REFERENCES <IRRELEVANT_TABLE> ("SEQ_ID")
) TABLESPACE DATA_TS PARTITION BY REFERENCE (FK_01) ENABLE ROW MOVEMENT;
now, the task is to move all the (C)LOBs from DATA_TS to newly allocated tablespace called LOB_TS.
For the first table, it is easy enough:
ALTER TABLE TAB_ONE MOVE LOB ("MESSAGE") store as (tablespace LOB_TS compress low);
For the other one, partitioning does all the trouble. The aforementioned command does not work for obvious reasons, so I managed to find another:
ALTER TABLE TAB_TWO MOVE PARTITION SYS_P18485 LOB (RESPONSE) STORE AS ( TABLESPACE LOB_TS COMPRESS LOW );
ALTER TABLE TAB_TWO MOVE PARTITION SYS_P18299 LOB (RESPONSE) STORE AS ( TABLESPACE LOB_TS COMPRESS LOW );
(one for each partition the table TAB_TWO has)
These ALTER TABLES do not fail per se. The SQL Developer proudly states "Table TAB_TWO altered."
But then I ran SELECT * FROM USER_LOBS WHERE TABLE_NAME = 'TAB_TWO' and found out, that the CLOB stayed in the previous tablespace and did not move.
Of course, the idea of copying data via Create Table as Select, dropping the table, creating a new table and restoring the data occurred to me, but I would prefer a cleaner solution without the need of duplicating large amounts of data to different tables.
Related
I am going to develop a reporting database by querying the production database once using a stored procedure.
The stored procedure will then write the result into it's own output tables.
Following is the schema for the output table:
Create table Output (
Customer_ID NUMBER(15) not null,
STD_HASH RAW(1000 BYTE) ,
VALID_PERIOD_START NOT NULL TIMESTAMP(6),
VALID_PERIOD_END NOT NULL TIMESTAMP(6),
Address VARCHAR2(30 CHAR),
period for valid_period(valid_period_start,valid_period_end),
Constraint Output_PK Primary Key ( Customer_ID, valid_period_start, valid_period_end )
)
As the stored procedure will perform a lot of update and delete statement on the output table, and those output table is very big. The largest one I have right now is 8GB. I am thinking to alter those output tables with the "SHRINK SPACE" option at the end of the stored procedure to reclaim some spaces.
Following is the statement that I am going to apply:
Alter table OUTPUT1 ENABLE ROW MOVEMENT; -- Temporary enable row movement for the table
Alter TABLE output2 SHRINK SPACE;
Alter table OUTPUT1 DISABLE ROW MOVEMENT;-- Disable row movement.
Those output tables are temporal table that is using the valid period and the ID from production as a primary key.
However, as I am very new with the Shrink Space function. Can anyone tell me what is the disadvantage of using this function?
The table, basically will not be updated from anywhere other than this stored procedure. The stored procedure will be scheduled to run in a daily base.
Thanks in advance!
yes, shrink has some restrictions:
(1) it locks the table during the shrink operation
(2) it change the rowid of the table.
(3) it needs the tablespace with automatic segment-space management enabled.
we have other alternatives to claim the unused space:
(1) export/import
(2) dbms_redefinition
I have the following PL/SQL code:
DROP TABLE TAB_PARAM;
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE TAB_PARAM
(
TABLE_OWNER VARCHAR2(30) NOT NULL,
TABLE_NAME VARCHAR2(30) NOT NULL,
COLUMN_NAME VARCHAR2(30) NOT NULL,
PATTERN VARCHAR2(1024),
TYPE_METHODE VARCHAR2(30) NOT NULL,
SEPARATEUR VARCHAR2(20),
ID VARCHAR2(30),
CONSTRAINT PK_TAB_PARAM PRIMARY KEY (TABLE_OWNER,TABLE_NAME,COLUMN_NAME) USING INDEX TABLESPACE IND_PARC_256M NOLOGGING
)
TABLESPACE TAB_PARC_256M NOLOGGING NOCACHE NOMONITORING NOPARALLEL';
commit;
END;
/
I don't understand the part :
CONSTRAINT PK_TAB_PARAM PRIMARY KEY (TABLE_OWNER,TABLE_NAME,COLUMN_NAME) USING INDEX TABLESPACE IND_PARC_256M NOLOGGING
Nor the part:
TABLESPACE TAB_PARC_256M NOLOGGING NOCACHE NOMONITORING NOPARALLEL';
I know that it is setting the ID as primary key of TAB_PARAM but then I do not get the index part.
Can anyone help me understand this code please?
Sometimes you can create a table in a disposable way , for example you need to read data via sqlloader from file and insert in table , after that you will select all records from table . This operation doesnt need indexes and doesnt need primary key . Anyway it is always good to create primary key when you create a table and Oracle will create index for you . You can create more indexes whenever you want since the table was created . Now suppose you wanna update the table using where condition on a field who is not a primary key , it could be a better decision create an index on that field . In addition when you create indexes or table , you can associate tablespaces (created before) and could be good practice separate tablespaces for tables and indexes . All those operations are DDL Statements . In Oracle you can check datafiles , tables and indexes with those queries select * from dba_data_files; select * from dba_tables; select * from dba_indexes;
For primary key oracle implicitly creates unique index in table's tablespace.
This part USING INDEX TABLESPACE allow us to indicate tablespace for this implicitly index.
NOLOGGING - data is modified with minimal logging (to mark new extents invalid and to record dictionary changes).
NOCACHE - Oracle doesn't store blocks in the buffer cache.
NOPARALLEL - Parallel execution is not allowed on this table.(Default value)
NOMONITORING - Disable statistics collection. Now is deprecated. There is other mechanism to collect statistic
Edit. from oracle doc
Oracle Database uses an existing index if it contains a unique set of values before enforcing the primary key constraint. The existing
index can be defined as unique or nonunique. When a DML operation is
performed, the primary key constraint is enforced using this existing
index.
If there already index hitting the pk columns , oracle will used it, else then Oracle Database generates a unique index.
so you can create a primary key in oracle without an index if there was already index for that columns , specifying an index is for performance issue. The purpose of an index in a table is to 'read' the data faster.
From the oracle document
An index is a schema object that contains an entry for each value that
appears in the indexed column(s) of the table or cluster and provides
direct, fast access to rows.
As for the TABLESPACE, its where the database object exists, so when you create a table you specify in which tablespace you want it to exists. Read more here oracle document
As for NOLOGGING NOCACHE NOMONITORING, so the table not to be logged in redo logs or cached, also related to performance issue.
In order to compress the data in a single partition, I use the following approach:
-- I create a table with the same structure of the ORIGINAL TABLE, but
-- on a new tablespace (NEW_TBS_DATA)
CREATE TABLE AUXILIARY_TABLE TABLESPACE NEW_TBS_DATA AS
SELECT * FROM ORIGINAL_TABLE WHERE 1=0
-- I create the index on the AUXILIARY_TABLE, on a new tablespace
-- for indexes (NEW_TBS_IDX)
CREATE INDEX I_1 ON AUXILIARY_TABLE( START_DATE) TABLESPACE NEW_TBS_IDX
CREATE INDEX I_2 ON AUXILIARY_TABLE( ID_FILE) TABLESPACE NEW_TBS_IDX
CREATE INDEX I_3 ON AUXILIARY_TABLE( DESCRIPTION) TABLESPACE NEW_TBS_IDX
CREATE INDEX I_4 ON AUXILIARY_TABLE( ZIP_CODE) TABLESPACE NEW_TBS_IDX
CREATE INDEX I_5 ON AUXILIARY_TABLE( BH_TRAFFIC) TABLESPACE NEW_TBS_IDX
-- I move data from partition 20160529 to auxiliary_table
ALTER TABLE ORIGINAL_TABLE EXCHANGE PARTITION PARTITION_20160529 WITH TABLE AUXILIARY_TABLE INCLUDING INDEXES WITHOUT VALIDATION
-- I compress data using the new tablespace NEW_TBS_DATA on auxiliary_table
ALTER TABLE AUXILIARY_TABLE MOVE TABLESPACE NEW_TBS_DATA PARALLEL 4 COMPRESS
-- I move the data back to the original table, with the same exchange statement:
ALTER TABLE ORIGINAL_TABLE EXCHANGE PARTITION PARTITION_20160529 WITH TABLE AUXILIARY_TABLE including indexes without validation
-- I drop the auxiliary_table
DROP TABLE AUXILIARY_TABLE CASCADE CONSTRAINTS PURGE
Why, at the end of the process, the partition INDEXES are on the old tablespace instead of the new tablespace (NEW_TBS_IDX)?
Section "including indexes" takes affect only for local indexes. See
https://docs.oracle.com/cd/E11882_01/server.112/e25523/part_admin002.htm
section(Exchanging Partitions)
I am a moderate user of Oracle and I had to create some of the tables in specified table space as shown below.
create table t_abc tablespace abc_tbspc as select * from abc;
create table t_xyz tablespace abc_tbspc as select * from xyz;
After running these through jobs (file containing around 5 tables to be created in a single tablespace), I could see that the table t_abc is created in abc_tbspc ; but the table t_xyz is assigned to null when I query the all_tables. Not sure why the 2nd table is not created in the specified tablespace even though there is abundant space in the table space.
TABLESPACE_NAME will be null for one of these reasons:
Temporary Temporary tables use a temporary tablespace.
Index Organized Index-organized tables store data in an index, not in a heap.
Partitioned Each partition could have a different tablespace, there is not necessarily one tablespace for the whole table.
External External tables do not store their data in a tablespace.
Your code should not meet one of the conditions above; did you leave out some details? I ran the query below to look for other cases where TABLESPACE_NAME is null but could not find any.
select *
from dba_tables
where tablespace_name is null
and (temporary is null or temporary <> 'Y') -- #1
and (iot_type is null or iot_type <> 'IOT') -- #2
and (partitioned is null or partitioned <> 'YES') -- #3
and (owner, table_name) not in -- #4
(select owner, table_name from dba_external_tables)
How can I alter a partitioned table (in Oracle 10g Database) to a new table space for not only the partitions but also the table itself? Which I mean is, I can do following without issues,
--sql
alter table abc move partition abc01 tablespace new_tablespace;
alter table abc move partition abc02 tablespace new_tablespace;
alter table abc move partition abc03 tablespace new_tablespace;
but somehow the table's definition is still associating with the old table space, and and I have moved all tables data off the old table space. If I query the dba_segment for the old table space, there is nothing there. My question is, may I drop the old table space, even no data in the data files in the old table space, but somehow those partitioned tables definitions still associating with the old table space?
Each partition must be moved, as you've discovered. If you want new partitions to be created in a different tablespace without specifying that new tablespace, you'd have to use the following:
alter table abc modify default attributes tablespace new_tablespace;