16 March, 2009

Materialized Views and Tables

Responding to a recent forums posting on a Materialized View having the same name as a Table, here I demonstrate the case.

In this example below, MV_1 is created as a Materialized View. Oracle automatically creates a table with the same name as the underlying table. This is for the storage of the data that the Materialized View, by definition, is supposed to be physically present .
When I later drop MV_1, the underlying table also gets dropped.

In the second case, MV_2 is actually a table. With the table pre-existing, I create a Materialized View on the Prebuilt Table. If I drop the Materialized View, table remains -- because it predates the MV definition.



SQL> connect test_user/test_user
Connected.
SQL> create table source_tb_1 (col_1 varchar2(5));

Table created.

SQL> create materialized view mv_1 as select * from source_tb_1;

Materialized view created.

SQL> select object_name, object_type from user_objects order by 1;

OBJECT_NAME OBJECT_TYPE
------------------------------ -------------------
MV_1 TABLE
MV_1 MATERIALIZED VIEW
SOURCE_TB_1 TABLE

SQL> select table_name from user_tables;

TABLE_NAME
------------------------------
SOURCE_TB_1
MV_1

SQL> drop materialized view mv_1;

Materialized view dropped.

SQL> select object_name, object_type from user_objects order by 1;

OBJECT_NAME OBJECT_TYPE
------------------------------ -------------------
SOURCE_TB_1 TABLE

SQL> select table_name from user_tables;

TABLE_NAME
------------------------------
SOURCE_TB_1

SQL> create table mv_2 (col_1 varchar2(5));

Table created.

SQL> create materialized view mv_2 on prebuilt table as select * from source_tb_1;

Materialized view created.

SQL> select object_name, object_type from user_objects order by 1;

OBJECT_NAME OBJECT_TYPE
------------------------------ -------------------
MV_2 TABLE
MV_2 MATERIALIZED VIEW
SOURCE_TB_1 TABLE

SQL> select table_name from user_tables ;

TABLE_NAME
------------------------------
SOURCE_TB_1
MV_2

SQL> drop materialized view mv_2;

Materialized view dropped.

SQL> select object_name, object_type from user_objects order by 1;

OBJECT_NAME OBJECT_TYPE
------------------------------ -------------------
MV_2 TABLE
SOURCE_TB_1 TABLE

SQL> select table_name from user_tables;

TABLE_NAME
------------------------------
SOURCE_TB_1
MV_2

SQL>



Thus, "MV_1" appears as both a Table and a Materialized View. Dropping the Materialized View results in the table being dropped. Conversely, "MV_2" is actually a Table with a Materialized View being defined over it. Dropping the Materialized View only drops the MV definition, the table remains.
.
.

11 March, 2009

Checking the status of a database

Most DBAs seem to be in the habit of using the command "ARCHIVE LOG LIST" to check a database (instance's) archivelog and archiver status.
However, this presupposes that you connect AS SYSDBA.
Similarly, many other postings I see on forums also assume either of
a. CONNECT / AS SYSDBA on the SQLPlus command line
b. Connection via a GUI (OEM or TOAD), where, I suspect, the connection is still done with AS SYSDBA.

I dislike using AS SYSDBA and prefer to use an account with less powerful privileges. An account with SELECT on specific views is generally sufficient to monitor a database. Such an account may have SELECT ANY DICTIONARY (or, *more preferably* SELECT_CATALOG_ROLE if you need to query only views and not query SYS tables directly) if you need it to be able to query any/all data dictionary and performance views. An account with such privileges can do no harm.

As a DBA, your first responsibility is towards the Data. As far as possible, work in such a manner that restricts you from harming/damaging data even inadvertently.

Logging in with an account with the DBA role should not be very frequent.
Logging in AS SYSDBA should be rare - very rare, in my opinion.


Here's an example where I do not need DBA and SYSDBA and I can check the status of a database. This method is particularly useful when you are monitoring multiple databases from a single "monitoring station", connected over SQL*Net :


ora10204>sqlplus

SQL*Plus: Release 10.2.0.4.0 - Production on Wed Mar 11 23:15:56 2009

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.

Enter user-name: / as sysdba

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> create user query_database identified by query_database;

User created.

SQL> grant create session to query_database;                      

Grant succeeded.

SQL> grant select on v$database to query_database;
grant select on v$database to query_database
               *
ERROR at line 1:
ORA-02030: can only select from fixed tables/views


SQL> grant select on v_$database to query_database;

Grant succeeded.

SQL> grant select on v_$instance to query_database;

Grant succeeded.

SQL> connect query_database/query_database@MYREMOTEDB
Connected.
SQL> select log_mode, archiver from
 2  (select log_mode from v$database), (select archiver from v$instance);

LOG_MODE     ARCHIVE
------------ -------
ARCHIVELOG   STARTED

SQL>  


Once I have an account called "QUERY_DATABASE" (or "MONITORING_ACCOUNT" or, even if you really need to use this "DBSNMP"), I do NOT need to login with the DBA role or the SYSDBA privilege for most monitoring scripts / queries.

07 March, 2009

Logical and Physical Storage in Oracle

Following my earlier post "RDBMS Software, Database and Instance", here's a quick note on Logical and Physical Storage in Oracle :


Data (whether tables or indexes) is stored in an Oracle database at "two" levels --
the Logical and the Physical.

The Logical level is of Tablespaces, Segments and Extents.
The Physical level is of Datafiles and Blocks.

When you create a Tablespace, you specify the DataFiles that the Tablespace will consist
of and the initial sizes of the DataFiles and whether Oracle may "autoextend" the DataFiles
on the same filesystems.
{When using the OMF (Oracle Managed Files) feature, datafile names and sizes and autoextend
are “automatically” set by Oracle but, nevertheless, do exist.}
A Tablespace consists of 1 or more DataFiles which can be on the same filesystem or on
different filesystems (i.e., mountpoints).

When you create a Table, you specify the Tablespace name and Extent allocation parameters
{Segment space management is isn't really about allocation of storage but about freelist
(blocks availabe for INSERTs) management}.
Thus the CREATE TABLE syntax identifies the Tablespace in which the Table's Segment
will be created and the sizes of the initial and next extents that will be allocated.
{If the Tablespace is created with Allocation Type MANUAL or AUTO, then the Table’s Extent
sizes are determined by the Allocation Type}.

Oracle then allocates the Extent(s) as groups of DatabaseBlocks in the available DataFiles
"belonging" to the Tablespace which that Segment exists in.

A Segment *cannot* span Tablespaces, it can fit into only 1 Tablespace. However, it can
have extents in different DataFiles of the Tablespace. Therefore, a Table (or Index) can
have Extents in different DataFiles, thus spreading the I/O and "hot spots". Similarly,
different Tables in a Tablespace may go into different DataFiles. However, it is difficult
for the DBA to pre-allocate specific DataFiles and Extents (other than using MINEXTENTS
during the CREATE or using ALLOCATE EXTENT with an ALTER command).

Note : When a Table (or Index) is Partitioned, each Partition is a separate Segment.
Therefore, Oracle allows you to place each Partition in a separate Tablespace because
each is a separate Segment.

An Extent cannot span DataFiles, the first and last block of the Extent are "contiguous"
within a DataFile.
{Oracle may "autoextend" a DataFile to increase it's size so as to allocate an extent in
the DataFile when necessary}.

When Row Chaining (a Row being larger than the Oracle BlockSize for DatabaseBlocks is
written across multiple DatabaseBlocks) or Row Migration (a Row is moved from one
DatabaseBlock to another because, on expansion of the RowLength by an Update, it cannot
fit into the original DatabaseBlock any longer), the Row is allocated space in another
block --whether in the same Extent or a different Extent -- in the same Segment.

Database (or Tablespace or DataFile) Backup using RMAN (or OS utilities like "cp" or
"tar" or "cpio" or NetBackup commands etc) is always a Physical Backup. The Backup
actually copies each DatabaseBlock without regard to the contents of the DatabaseBlock.
Therefore, it also follows that Recovery has to be Physical -- a RollForward using the
Archived RedoLogs (aka ArchiveLogs) has to "re-apply" changes to each DatabaseBlock.
This is possible because each DatabaseBlock header includes the "SCN" to identify the
point in time of the last update to the DatabaseBlock and the RedoStream in the RedoLogs
consists of Change Vectors which identify the DatabaseBlocks being impacted (whether by
Insert, Update or Delete) by execution of a DML. Therefore, during the RollFoward,
Oracle merely identifies the DatabaseBlocks from the RedoStream and "reapplies" the
changes to the Blocks. All this is at the "Physical" level.

Export and Import based "backup" and "recovery" mechanisms are Logical because they
operate at the individual Table level (or even against specific Rows, if the Export is
done with a Query).