Thursday, December 2, 2010

Oracle Data Pump

0comments
The Data Pump utility was introduced from Oracle 10g R1 onwards. This boasts very high data transfer between databases. The Data Pump provides two utilities as mentioned below:
  • Data Pump Export : expdp
  • Data Pump Import : impdp
They might seem similar to the traditional exp and imp commands but they actually aren't! The export files from expdp cant be imported using the traditional import command imp. Also export files from exp cant be imported using impdp. The utilities are server related rather than client related with regard to the traditional ones.

Okay, enough of theories! Let's look at some examples:

Step 1: Log into the database as SYS user:
splus sys as sysdba
Step 2: Creating directory for dumping and setting permissions
create directory DUMPDIR as '/home/oracle/dumpdir';
Grant necessary permissions for the user who needs the export their schema:
grant read,write on directory dumpdir to user1;
Step 3: Exporting the schema
expdp user1/passwd DIRECTORY=DUMPDIR DUMPFILE=user1.expdp.dmp SCHEMAS=user1;
Step 4: Importing the schema
impdp user1/password DIRECTORY=DUMPDIR DUMPFILE=user1.expdp.dmp SCHEMAS=user1;

Oracle wont start: ORA-27300, ORA-27301, ORA-27302 (No space left on device)

0comments
Ever encountered this error while starting up your Oracle database? At first glance, as the error informs with the line familiar to most administrators "No space left on device", its not actually what you think it is!

Even if you have loads of HDD space and free memory left, this error can happen. Its because you don't have enough semaphores left. A semaphore is a value in a designated place in operating system (or kernel) storage that each process can check and then change (ref).
ORA-27154: post/wait create failed
ORA-27300: OS system dependent operation:semget failed with status: 28
ORA-27301: OS failure message: No space left on device
ORA-27302: failure occurred at: sskgpsemsper
To fix this error, edit your /etc/sysctl.conf file and add/modify the below parameter to the values mentioned below:
kernel.sem = 250 32000 100 128
Now to apply these changes, run the below command:
sysctl -p
Once its done, try starting your database. It should start without the previous error.

Oracle Export and Import - The Traditional Way!

0comments
Even though its possible to pass the requires parameters during exp or imp command run time, its convenient to use single-line full commands when its to be used in an automated export/import scripts:

Complete Database Export:

To export the complete Oracle Database and import it to another machine, it requires SYSTEM user privileges. Here is how its done:
exp SYSTEM/password FULL=y FILE=completedb.dmp LOG=dba.log CONSISTENT=y
 Here:

Full=y : denotes a complete database export is required.
FILE=filename.dmp : denotes the file name of the export file.
LOG=logname.log : denotes the log file to be written.
CONSISTENT=y : denotes no further changes shall be affected in the export file.

To import the complete database in another machine, here is how to do it:

imp SYSTEM/password FULL=y FIlE=completedb.dmp commit=y

User Schema Export:

An user can export his/her own schema using the below command:
exp username/password FILE=userdb.dmp OWNER=username

To import the schema, the below command shall be used:
imp SYSTEM/password FROMUSER=username1 TOUSER=username2 FILE=userdb.dmp
Here "username1" is the name of the user who exported the schema and "username2" is the name of the user to which the schema needs to be imported.

User Schema Export (Table specific):

To export a schema with only selected tables: 
exp username/password FILE=userdb-tables.dmp TABLES=(table1,table2)

To import that export file back to another user, the below command shall be used:
imp SYSTEM/password FROMUSER=username1 TOUSER=username2 FILE=userdb-tables.dmp TABLES=(table1,table2)

Thursday, October 7, 2010

Finding schema size in Oracle using SQLPlus CLI

0comments
To find out the schema size for a particular user, login as the user into the schema using SQLPlus CLI:

sqlplus schemauser/password
Once logged in, execute the below query:
SELECT sum(bytes)/1024/1024 FROM user_segments;
As per the calculation above (1024/1024), the output will be in MB.

Sample output shown below:

SUM(BYTES)/1024/1024
-------------------
12.4375

Tomcat: Deploying an application in direct URL with port 80

0comments
Ever had a requirement of deploying a Tomcat Web Application such that you need to get that under http://example.com instead of http://example.com:8080/webapp.

Here is what needs to be done:


1. Run the Tomcat Server in port 80 instead of port 8080:

This can be done under the server.xml file present under "tomcat_home/conf". Open the server.xml file and find the part that says:
Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"

Change that to the below form:
Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"
Once done, the application will be accessible under http://example.com/webapp

2. Setting a web app to Document Root

There are two easier methods for doing this:

a) The ROOT folder:

By default, the ROOT folder of the Tomcat Server is showing the default Tomcat page. So backup that folder to another suitable location (apart from the "webapps" folder. Now either rename your application folder to the name ROOT (please note that it should be in capitals) or create a soft link for that folder with the name ROOT:
$ mv tomcatapp ROOT

or
$ ln -s tomcatapp ROOT

b) Re-direction method:

Edit the file tomcat_home/webapps/ROOT/index.html, delete everything (after taking a backup) and place the below content in it:










Change the http://example.com to your required URL.

Now, your application shall be accessible under http://example.com itself. Easier for the clients to access ;-)


Note: There are other methods also for doing this.

Thursday, September 30, 2010

Oracle: Compression, Partitioning & Pruning

1 comment
"What I have written below is actually the notes I have taken when I tried to learn Oracle Partitioning, Table/Tablespace Compression and Partition Pruning. I know its not a technically advanced write up, but I guess it will help beginners like me to get started with this heavily vast topic"

Disclaimer:

Most of what written below has been taken from other websites. The examples mentioned in this blog worked out for me but I give no guarantee that it will work on another machine without proper study.

TABLE and TABLESPACE Compression

Table compression was introduced in Oracle 9i as a space saving feature for data warehousing projects. In 11g it is now considered a mainstream feature that is acceptable for OLTP databases. In addition to saving storage space, compression can result in increased I/O performance and reduced memory use in the buffer cache.

TABLESPACE with OLTP Compression

sql> CREATE TABLESPACE TB_COMPRESSED datafile '/home/oracle/app/oracle/oradata/TB_COMPRESSED.dbf' size 10000M DEFAULT COMPRESS FOR ALL OPERATIONS;

User Creation:

1. Since we created the tablespace with compression enabled, we can create an user on that tablespace.

sql> create user ORAUSER identified by perfomix_test default tablespace TB_COMPRESSED;

2. Once the user is created, necessary grants needs to be provided for the user for normal operations.

 
sql> grant CREATE TABLE, CREATE SESSION, CREATE TRIGGER, CREATE VIEW, CREATE SEQUENCE, CREATE PROCEDURE to ORAUSER;


3. Setting quota for the user.
 

sql> alter user ORAUSER quota unlimited on TB_COMPRESSED;

Oracle Partitioning

Partitioning allows a table, index, or index-organized table to be subdivided into smaller pieces, where each piece of such a database object is called a partition. Each partition has its own name, and may optionally have its own storage characteristics.

From the perspective of a database administrator, a partitioned object has multiple pieces that can be managed either collectively or individually. This gives the administrator considerable flexibility in managing partitioned objects. However, from the perspective of the application, a partitioned table is identical to a non-partitioned table; no modifications are necessary when accessing a partitioned table using SQL queries and DML statements.

Partitioning can provide tremendous benefit to a wide variety of applications by improving performance, manageability, and availability. It is not unusual for partitioning to improve the performance of certain queries or maintenance operations by an order of magnitude. Moreover, partitioning can greatly simplify common administration tasks.

Oracle Partitioning offers three fundamental data distribution methods as basic partitioning strategies that control how data is placed into individual partitions:

Range Partitioning: This maps data to partitions based on ranges of values of the partitioning key that you establish for each partition. It is the most common type of partitioning and is often used with dates.

Hash Partitioning: This maps data to partitions based on a hashing algorithm that Oracle applies to the partitioning key that you identify. The hashing algorithm evenly distributes rows among partitions, giving partitions approximately the same size.

List Partitioning: This enables you to explicitly control how rows map to partitions by specifying a list of discrete values for the partitioning key in the description for each partition. The advantage of list partitioning is that you can group and organize unordered and unrelated sets of data in a natural way.

Here I am going to discuss more about RANGE partitioning in this blog.

Creating a Partitioned Table (Range Partitioning) with OLTP Compression:

Below shown is an example of Range Partitioning in Oracle. The CREATE query will have the clause "PARTITION BY RANGE(field_name)" and the partitions are defined one-by-one with a distinctive name. A clause "VALUES LESS THAN" is mandatory for defining the partition end-points.

Example:

CREATE TABLE SAMPLE_ORDERS
(ORDER_NUMBER NUMBER,
ORDER_DATE DATE,
CUST_NUM NUMBER,
TOTAL_PRICE NUMBER,
TOTAL_TAX NUMBER,
TOTAL_SHIPPING NUMBER)
PARTITION BY RANGE(ORDER_DATE)
(
PARTITION P1 VALUES LESS THAN(TO_DATE('01-JAN-2010', 'DD-MON-YYYY')) COMPRESS FOR ALL OPERATIONS,
PARTITION P2 VALUES LESS THAN(TO_DATE('01-FEB-2010', 'DD-MON-YYYY')) COMPRESS FOR ALL OPERATIONS,
PARTITION P3 VALUES LESS THAN(TO_DATE('01-MAR-2010', 'DD-MON-YYYY')) COMPRESS FOR ALL OPERATIONS,
PARTITION P4 VALUES LESS THAN(TO_DATE('01-APR-2010', 'DD-MON-YYYY')) COMPRESS FOR ALL OPERATIONS,
PARTITION P5 VALUES LESS THAN(TO_DATE('01-MAY-2010', 'DD-MON-YYYY')) COMPRESS FOR ALL OPERATIONS,
PARTITION P6 VALUES LESS THAN(TO_DATE('01-JUN-2010', 'DD-MON-YYYY')) COMPRESS FOR ALL OPERATIONS,
PARTITION P7 VALUES LESS THAN(TO_DATE('01-JUL-2010', 'DD-MON-YYYY')) COMPRESS FOR ALL OPERATIONS,
PARTITION P8 VALUES LESS THAN(TO_DATE('01-AUG-2010', 'DD-MON-YYYY')) COMPRESS FOR ALL OPERATIONS,
PARTITION P9 VALUES LESS THAN(TO_DATE('01-SEP-2010', 'DD-MON-YYYY')) COMPRESS FOR ALL OPERATIONS
);


This should create a table with 9 range partitions along with enabling OLTP compression.

Now we can insert some dummy values to the table for testing. As you can see, there is no changes with the INSERT queries even if its done against a partitioned table. Oracle manages the input data and store them into respective partitions.

sql> INSERT INTO SAMPLE_ORDERS values ('200', '05-FEB-2010', '200', '2000', '2222', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('300', '05-MAR-2010', '300', '3000', '3333', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('400', '05-APR-2010', '400', '4000', '4444', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('500', '05-MAY-2010', '500', '5000', '5555', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('600', '05-JUN-2010', '600', '6000', '6666', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('700', '05-JUL-2010', '700', '7000', '7777', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('800', '05-AUG-2010', '800', '8000', '8888', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('101', '02-JAN-2010', '100', '1000', '1111', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('201', '02-FEB-2010', '200', '2000', '2222', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('301', '02-MAR-2010', '300', '3000', '3333', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('401', '02-APR-2010', '400', '4000', '4444', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('501', '02-MAY-2010', '500', '5000', '5555', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('601', '02-JUN-2010', '600', '6000', '6666', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('701', '02-JUL-2010', '700', '7000', '7777', '1111');
sql> INSERT INTO SAMPLE_ORDERS values ('801', '02-AUG-2010', '800', '8000', '8888', '1111');


SELECT Queries:

Just like the INSERT queries, the SELECT queries can also be used without any kind of modifications relation to partitioning.

  SQL> select * from SAMPLE_ORDERS

How ever, its also possible to SELECT data from specific partitions by giving the partition name.

  SQL> select * from SAMPLE_ORDERS PARTITION(P2);

  ORDER_NUMBER ORDER_DAT     CUST_NUM TOTAL_PRICE  TOTAL_TAX TOTAL_SHIPPING
  ------------ --------- ---------- ----------- ---------- --------------
    101                  02-JAN-10          100            1000        1111       1111


  SQL> select * from SAMPLE_ORDERS PARTITION(P3);

  ORDER_NUMBER ORDER_DAT     CUST_NUM TOTAL_PRICE  TOTAL_TAX TOTAL_SHIPPING
  ------------ --------- ---------- ----------- ---------- --------------
     200 05-FEB-10          200     2000        2222       1111
     201 02-FEB-10          200     2000        2222       1111


Checking on Partition and Compression Details

Since we created the partitions using "COMPRESS FOR ALL OPERATIONS", its ideal for heavy-transaction databases like OLTP. We can find the details of the Partitions and Compression details using the below query:

  SQL> SELECT partition_name, compression, compress_for FROM user_tab_partitions;

  PARTITION_NAME               COMPRESS COMPRESS_FOR
  ------------------------------ -------- ------------
  P1                   ENABLED    OLTP
  P2                   ENABLED    OLTP
  P3                   ENABLED    OLTP
  P4                   ENABLED    OLTP
  P5                   ENABLED    OLTP
  P6                   ENABLED    OLTP
  P7                   ENABLED    OLTP
  P8                   ENABLED    OLTP
  P9                   ENABLED    OLTP

Modifying Partitions in a table

Adding a new partition:

sql>  alter table tempabc add partition p2 values less than ('C%');

Note:
  1. You cannot move a partition with sub-partitions
  2. Each subpartition must be individually moved.
  3. We can add a partition to the high end of the table (after the last existing partition). If the first element of the partition bound of the high partition is MAXVALUE, you cannot add a partition to the table. You must split the high partition.   
  4. You can add a partition to a table even if one or more of the table indexes or index partitions are marked UNUSABLE.   
  5. You must use the SPLIT PARTITION clause to add a partition at the beginning or the middle of the table.     
  6. ALTER TABLE DROP PARTITION drops a partition and its data. If you want to drop a partition but keep its data in the table, you must merge the partition into one of the adjacent partitions.    
  7. If you drop a partition and later insert a row that would have belonged to the dropped partition, the row will be stored in the next higher partition. However, if you drop the highest partition, the insert will fail because the range of values represented by the dropped partition is no longer valid for the table.

Ways to partition an existing table

Method 1:
  • create a PARTITIONED table
  • load the NON-PARTITIONED data into the PARTITIONED table
  • drop the NON-PARTITIONED table
  • rename PARTITIONED table to whatever is appropriate
Method 2:
  • export table and data
  • drop table
  • create new partitioned table the way you want it
  • import table data into new partitioned table (this should also create all the necessary indexes and constraints from your original table)
Partition Pruning


Semantics-based partitioning can allow Adaptive Server to eliminate certain partitions when performing a search. Range-based partitions, for example, contain rows whose partitioning keys are discrete value sets. When a query predicate—a where clause—is based on those partitioning keys, Adaptive Server can quickly ascertain whether rows in a particular partition can satisfy the query. This behavior is called partition pruning, or partition elimination, and it can save considerable time and resources during execution.

For range and list partitioning – Adaptive Server can apply partition pruning on equality (=) and range (>, >=, <, and <=) predicates on partition-key columns on a single table.

Sample Queries:

Example 1:

sql> select * from sample_orders WHERE ORDER_DATE BETWEEN TO_DATE ('01-JAN-2010','DD-MON-YYYY') AND TO_DATE('01-MAR-2010','DD-MON-YYYY');

Result:

  ORDER_NUMBER ORDER_DAT     CUST_NUM TOTAL_PRICE  TOTAL_TAX TOTAL_SHIPPING
  ------------ --------- ---------- ----------- ---------- --------------
     100 05-JAN-10          100     1000        1111       1111
     101 02-JAN-10          100     1000        1111       1111
     200 05-FEB-10          200     2000        2222       1111
     201 02-FEB-10          200     2000        2222       1111

Example 2:

  SQL> select * from sample_orders where ORDER_DATE > ('01-JUN-2010');

Result:

  ORDER_NUMBER ORDER_DAT     CUST_NUM TOTAL_PRICE  TOTAL_TAX TOTAL_SHIPPING
     ------------             ---------              ----------     ----------- ---------- --------------
     600                   05-JUN-10      600     6000      6666     1111
     601                   02-JUN-10      600     6000      6666     1111
     700                   05-JUL-10      700     7000       7777     1111
     701                   02-JUL-10      700     7000       7777     1111
     800                   05-AUG-10    800     8000        8888    1111
     801                   02-AUG-10    800     8000        8888       1111


More Examples:

Partition on a numeric value range:

  CREATE TABLE emp (
   empno NUMBER(4),
   ename VARCHAR2(30),
   sal   NUMBER
  )
  PARTITION BY RANGE(empno) (
    partition e1 values less than (1000)     tablespace ts1,
    partition e2 values less than (2000)     tablespace ts2,
    partition e3 values less than (MAXVALUE) tablespace ts3
  );


Partition on a VARCHAR2 string:

  CREATE TABLE emp
   ( id        NUMBER(5)    PRIMARY KEY,
     name      VARCHAR2(50) NOT NULL,
     phone     VARCHAR2(15),
     email     VARCHAR2(100) 

   )
   PARTITION BY RANGE ( name )
     ( 

       PARTITION p1 VALUES LESS THAN ('L')      TABLESPACE ts1,
       PARTITION p2 VALUES LESS THAN (MAXVALUE) TABLESPACE ts2
     );


Time based range partitioning:

CREATE TABLE t1 (id NUMBER, c1 DATE)
  PARTITION BY RANGE (c1)
    (PARTITION t1p1 VALUES LESS THAN (TO_DATE('2007-11-01', 'YYYY-MM-DD')),
     PARTITION t1p2 VALUES LESS THAN (TO_DATE('2007-12-01', 'YYYY-MM-DD')),
     PARTITION t1p3 VALUES LESS THAN (TO_DATE('2008-01-01', 'YYYY-MM-DD')),
     PARTITION t1p4 VALUES LESS THAN (MAXVALUE)
    );

Saturday, August 22, 2009

Oracle Database : Complete Export and Import

0comments
Suppose, we need to export all the Oracle schema in one step, similar
to "--all-databases" option in MySQL. In such cases, here is how its done:
exp USERID=system/password@sid file=complete_bak.dmp log=/tmp/full.log FULL=Y;
This should export all the databases in one step and will store that to a single file.

Now to import that back, here is what needs to be done.
imp system/password@sid file=complete_bak.dmp log=/tmp/full.log full=y ignore=y
Note:

* Will work only if ORACLE_HOME is same on both servers
* Create tablespace on the new server before importing the database. Else this wont work.
 

A Linux Admin's WeBlog! Blak Magik is Designed by productive dreams for smashing magazine Bloggerized by Ipiet The Blog Full of Games © 2008