Oracle segment space - oracle

I have a Tablespace with some tables and I can insert data without problem. Now I want to create a new table and I get this:
00000 - "unable to create INITIAL extent for segment in tablespace %s"
*Cause: Failed to find sufficient contiguous space to allocate INITIAL
extent for segment being created.
My question is: if there is a space problem, why am I able to insert data but not create new tables?
This is the CREATE script:
CREATE TABLE EC_SYS_NOTIFY_KYC (
ID NUMBER(38,0) PRIMARY KEY,
ID_OP NUMBER(38,0),
PROCESS_ID VARCHAR2(50) NOT NULL,
SYSTEM_ID VARCHAR2(50) NOT NULL)
TABLESPACE ECONTKYC_LARGE_1;

Space in Oracle is allocated in chunks called 'extents'. Your existing tables have already been allocated extents containing enough space to allow inserts for now, but you don't have enough unallocated free space in the tablespace to add a whole new extent, which is needed for a new table.
Eventually inserts into existing tables will start to fail as well, when their existing space is used up and they need more.

Related

Initial Extent for a table gets allocated only after data insertion in Locally managed user tablespace

In case of Locally managed SYSTEM tablespace, when objects are created in a user tablespace (which is also locally managed) initial extents are getting allocated only after data insertion.
Whereas in the same scenario where SYSTEM tablespace is dictionary managed, initial extent gets allocated whenever table is created.
create tablespace lmt datafile 'df.f' size 5M extent management local;
conn scott/tiger
create table sample (id nuber) tablespace lmt;
select * from user_tables where table_name = 'SAMPLE';
initial extent is null when SYSTEM tablespace is Locally managed
initial extent has value when SYSTEM tablespace is dictionary managed
After data insertion, initial extent is allocated in case (1)
Is this the expected behavior? because as per Oracle docs, 'Oracle allocates space for initial extent when you create the schema object'
I think you're quoting (or rather, slightly paraphrasing) this part of the documentation:
INITIAL
Specify the size of the first extent of the object. Oracle allocates space for this extent when you create the schema object. ...
That isn't the whole story though. Tables can be created with deferred segment creation:
deferred_segment_creation
Use this clause to determine when the database should create the segment(s) for this table:
SEGMENT CREATION DEFERRED: This clause defers creation of the table segment — as well as segments for any LOB columns of the table, any indexes created implicitly as part of table creation, and any indexes subsequently explicitly created on the table — until the first row of data is inserted into the table. ...
SEGMENT CREATION IMMEDIATE: The table segment is created as part of this CREATE TABLE statement.
It looks like what you are seeing is nothing to do with the SYSTEM tablespace being locally managed, as you suspected, and that is just a coincidence. The difference is the default for segment creation, which is controlled by an initialisation parameter, deferred_segment_creation. From what you've shown that is set to TRUE in the database that has the locally-managed SYSTEM tablespace, and FALSE in the one that has that dictionary-managed.
You can get consistent behaviour by overriding the default, either to defer creation:
create table sample (id number) segment creation deferred tablespace lmt;
Table SAMPLE created.
set null "(null)"
select initial_extent from user_tables where table_name = 'SAMPLE';
INITIAL_EXTENT
--------------
(null)
or to create immediately:
create table sample (id number) segment creation immediate tablespace lmt;
Table SAMPLE created.
select initial_extent from user_tables where table_name = 'SAMPLE';
INITIAL_EXTENT
--------------
65536
Or you could change the initialisation parameters to be the same, of course, but that's more work and might affect other code that assumes the current behaviour.

Tablespace Segments and Schema Objects

I am learning about tablespaces, but I am not sure what a segment of a tablespace constitutes. Is it safe to say that the following query displays all schema objects that can be moved to different tablespaces:
select distinct segment_type
from dba_segments;
Result:
SEGMENT_TYPE
------------------
LOBINDEX
INDEX PARTITION
TABLE SUBPARTITION
ROLLBACK
TABLE PARTITION
NESTED TABLE
LOB PARTITION
LOBSEGMENT
INDEX
TABLE
TYPE2 UNDO
CLUSTER
A segment represents the storage associated with an object such as a table or index. Segments reside in tablespaces.
You probably won't be moving rollback or undo segments, as those will be in their own dedicated tablespace and are system-managed in recent versions of Oracle.
I don't think there is a convenient way to move a cluster to a new tablespace, but then aside from the ones used internally for the data dictionary they are rarely used, so probably you won't have to deal with those either.

PL/SQL Creating a table with indexes

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.

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;

Oracle Database: How can I alter a partitioned table to a new table space for not only the partitions but also the table itself?

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;

Resources