Question

I am writing a data conversion in PL/SQL that processes data and loads it into a table. According to the PL/SQL Profiler, one of the slowest parts of the conversion is the actual insert into the target table. The table has a single index.

To prepare the data for load, I populate a variable using the rowtype of the table, then insert it into the table like this:

insert into mytable values r_myRow;

It seems that I could gain performance by doing the following:

  • Turn logging off during the insert
  • Insert multiple records at once

Are these methods advisable? If so, what is the syntax?

Was it helpful?

Solution

It's much better to insert a few hundred rows at a time, using PL/SQL tables and FORALL to bind into insert statement. For details on this see here.

Also be careful with how you construct the PL/SQL tables. If at all possible, prefer to instead do all your transforms directly in SQL using "INSERT INTO t1 SELECT ..." as doing row-by-row operations in PL/SQL will still be slower than SQL.

In either case, you can also use direct-path inserts by using INSERT /*+APPEND*/, which basically bypasses the DB cache and directly allocates and writes new blocks to data files. This can also reduce the amount of logging, depending on how you use it. This also has some implications, so please read the fine manual first.

Finally, if you are truncating and rebuilding the table it may be worthwhile to first drop (or mark unusable) and later rebuild indexes.

OTHER TIPS

Regular insert statements are the slowest way to get data in a table and not meant for bulk inserts. The following article references a lot of different techniques for improving performance: http://www.dba-oracle.com/oracle_tips_data_load.htm

If dropping the index doesn't speed things up enough, you need the Oracle SQL*Loader:

http://www.oracle.com/technology/products/database/utilities/htdocs/sql_loader_overview.html

Suppose you have taken eid,ename,sal,job. So create a table first as:

SQL>create table tablename(eid number, ename varchar2(20),sal number,job char(10));

Now insert data:-

SQL>insert into tablename values(&eid,'&ename',&sal,'&job');

Drop the index, then insert the rows, then re-create the index.

Check this link http://www.dba-oracle.com/t_optimize_insert_sql_performance.htm

  1. main points to consider for your case is to use Append hint as this will directly append into the table instead of using freelist. If you can afford to turn off logging than use append with nologging hint to do it
  2. Use a bulk insert instead instead of iterating in PL/SQL
  3. Use sqlloaded to load the data directly into the table if you are getting data from a file feed

Maybe one of your best option is to avoid Oracle as much as possible actually. I've been baffled by this myself, but very often a Java process can outperform many of the Oracle's utilities which either use OCI (read: SQL Plus) or will take up so much of your time to get right (read: SQL*Loader).

This doesn't prevent you to use specific hints either (like /APPEND/).

I've been pleasantly surprised each time I've turned to that kind of solution.

Cheers,

Rollo

Here are my recommendations on fast insert.

Trigger - Disable any triggers associated with a table. Enable after Inserts are complete.

Index - Drop Index and re-create it after your Inserts are complete.

Stale stats - Re-analyze table and index stats.

Index de-fragmentation - Rebuild Index if needed Use No Logging -Insert using INSERT APPEND (Oracle only). This approach is very risky approach, no redo logs are generated therefore you can’t do a rollback - make a backup of table before you start and don't try on live tables. Check if your db has similar option

Parallel Insert: Running parallel insert will get the job faster.

Use Bulk Insert Constraints - Not much overhead during inserts but still a good idea to check, if it is still slow after even after step 1

You can learn more on http://www.dbarepublic.com/2014/04/slow-insert.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top