What is Native Compilation?
How does PL/SQL Native Compilation Work?
What's new in Oracle Database 10g?
What objects can be the subject of PL/SQL Native Compilation?
What is the naming convention for the Shared Libraries (DLLs)?
Are the shared dynamically linkable libraries portable?
Do I need a C compiling environment at the deployment site(s)?
Which Oracle parameters are relevant to native compilation?
plsql_native_library_dir parameter
plsql_native_library_subdir_count parameter
plsql_code_type parameter
Format of the $ORACLE_HOME/plsql/spnc_commands File
In which dictionary table are the shared libraries generated by native compilation stored?
What happens to the shared library on the file system when I drop a NATIVE unit?
How do I change plsql_native_library_dir?
Are there any other circumstances where I need to delete a shared library by hand?
What if I delete a shared library by mistake?
Does Oracle Corp recommend mixing NATIVE and INTERPRETED units?
Do I need to regenerate the native shared libraries on an OS upgrade?
Can I use native mode to save time during application deployment (by shipping pre-generated NCOMP shared libraries)?
Test driving native compilation: Simple Test
Natively Compiling all PL/SQL units in the database
What is Native Compilation?
You can speed up the execution of PL/SQL modules (packages, triggers, procedures,
function, and types) by compiling them into native code
residing in shared libraries. The procedures are translated into
C code, then compiled with a C compiler and dynamically linked into
the Oracle process.
You can use this technique with both the supplied Oracle packages, and
procedures you write yourself. Procedures compiled this way work in all server
environments, such as the shared server configuration (formerly known as
multi-threaded server) and Oracle Real Application Clusters.
Performance
experiments (published on OTN), using a large set of representative test
programs, indicate that in Oracle Database 10g pure PL/SQL programs
applications can expect to see performance improvements ranging from a factor
of about 1.05 to 2.4, comparing speed when compiled native with
speed when compiled interpreted and holding everything else
constant. The size of the improvement depends upon the nature of the program.
Note: Many of the Oracle-supplied packages (such as UTL_FILE,
UTL_RAW, DBMS_LOB) are already implemented in C, with PL/SQL simply exposing
the API. These are not likely to benefit significantly from NATIVE compilation.
Similarly, PL/SQL program units that just call SQL statements might see little
or no speedup. However, natively compiled PL/SQL is always at least as fast as
the corresponding interpreted code. The compiled code makes the same library
calls as the interpreted code would, so its behavior is exactly the same.
Back to top
How does PL/SQL Native Compilation Work?
If you do not use native compilation, each PL/SQL program unit is compiled into
an intermediate form, machine-readable code (MCode). The MCode is stored in
the database dictionary and interpreted at run time.
With PL/SQL native compilation, the PL/SQL program is compiled into machine
native code that bypasses all the runtime interpretation, giving faster runtime
performance.
PL/SQL uses the command file $ORACLE_HOME/plsql/spnc_commands, and
the supported operating system C compiler and linker, to compile and link the
resulting C code into shared libraries. The shared libraries are stored in
the data dictionary, so that they can be backed up automatically and are
protected from being deleted. These shared library files are copied to the
filesystem and are loaded and run when the PL/SQL subprogram is invoked. If the
files are deleted from the filesystem while the database is shut down, or if
you change the directory that holds the libraries, they are extracted again
automatically.
Back to top
What's new in Oracle Database 10g?
This feature now requires less setup and maintenance.
A package body and its spec do not need to be compiled with the same
setting for code type. For example, a package body can be compiled natively
while the package spec is compiled interpreted.
Natively compiled subprograms are stored in the database, and the
corresponding shared libraries are extracted automatically as needed. You do
not need to worry about backing up the shared libraries, cleaning up old shared
libraries, and so on.
The initialization parameters and command setup for native compilation
have been simplified. The only required parameter is plsql_native_library_dir. The
parameters related to the compiler, linker, and make utility have been
obsoleted. The $ORACLE_HOME/plsql/spnc_commands
commands file is used for native compilation. It contains
commands and options for compiling and linking. here is no longer a
dependency on a make utility. The parameters plsql_native_make_utility and
plsql_native_make_file_name are no longer needed or supported. plsql_native_library_dir must still be specified like in
version 9.0.1 and version 9.2.0. This specifies the full path of the directory
where the shared libraries will be generated before being copied to the
database.
Any errors that occur during native compilation are reflected in the
USER_ERRORS dictionary view and by the SQL*Plus command SHOW ERRORS.
Native compilation is turned on and off by a separate initialization
parameter, plsql_code_type, rather
than being one of several options in the plsql_compiler_flags parameter, which is now deprecated.
RAC support: PL/SQL native compilation is now supported in RAC
environments that do not have a cluster (shared) file system.
Shared library cleanup: When a natively compiled PL/SQL module
is dropped (or recompiled in interpreted mode), the file system copy of
the shared library (in the location specified by the
plsql_native_library_dir) is now deleted. In RAC configuration,
the shared library is deleted from all instances.
Back to top
What objects can be the subject of PL/SQL
Native Compilation?
Any stored PL/SQL module can be natively compiled. Anonymous PL/SQL blocks
are never natively compiled.
Note: Oracle supports the following types of stored PL/SQL modules:
FUNCTION
PACKAGE
PACKAGE BODY
PROCEDURE
TRIGGER
TYPE
TYPE BODY
Back to top
What is the naming convention for the Shared Libraries (DLLs)?
Native compilation generates a shared library per unit. For example, a
shared library will be generated for the package specification as well as
one for the package body. Some examples of generated names are:
PKG__SCOTT__S__54682.so
PKG__SCOTT__B__54683.so
The generated name typically includes the unit name, schema name, the
type of object and the object number. However, this is an internal convention that is
subject to change and users should not rely on the specifics of the
filename format.
The file name extensions might be different on different platforms.
For instance, on Solaris the shared libraries have a ".so" suffix whereas
on HP-UX, the shared libraries have a ".sl" suffix.
Back to top
Are the shared dynamically linkable libraries portable?
No, absolutely not! The shared libraries contain platform specific
object code.
Note: MCode generated in the interpreted
regime is also platform specific.
Back to top
Do I need a C compiler environment at the deployment
site(s)?
Yes. Non-negotiably. PL/SQL units may need to be compiled at the deployment
site and PL/SQL native compilation relies on a C compiler to generate object
(machine) code.
For instance, various actions (such as adding a column to a table) may cause
automatic invalidation of PL/SQL units (that depend on the table). Subsequent
access to such a unit will trigger a recompilation. Under such a circumstance,
the C compiler environment is needed to recompile the unit in
native mode again.
Another situation is when a patch fix needs to be applied on a deployment
database. Individual packages may need to be reloaded and compiled
in a deployment environment.
Back to top
Which Oracle parameters are relevant to
native compilation?
Back to top
plsql_native_library_dir
parameter
This parameter specifies the location of the directory where the OS copy
of shared libraries (DLLs) are kept.
When a module is natively compiled, the shared libary is created in this
location and then copied into the database dictionary table (ncomp_dll$).
Although the master copy of the shared library resides in the database, the
shared objects are also materialized in the file system so that they
can be dynamically loaded into the Oracle's address space.
Note 1: Users (DBAs) must never delete the shared libraries manually from
the plsql_native_library_dir when the system is up and running as these
DLLs may be mapped to Oracle processes. The only time it is safe to delete the
OS copy of a shared library is when the system is down.
Note 2: In RAC configuration, this parameter must be set in each
instance. The instances are not required to have a shared file system.
On each instance the plsql_native_library_dir can be set
to point to an instance local directory. Alternately, if the RAC
configuration supports a shared (cluster) file system, you can use a
common directory (on the shared file system) for all instances.
Note 3: You must create this directory. Oracle will not automatically
create this directory for you.
Note 4: Oracle Corp does not support NFS mounted directories for
plsql_native_library_dir either in a single instance or a RAC
case. This is because NFS causes some unpredictable timing errors while writing
or deleting files.
Back to top
plsql_native_library_subdir_count
parameter
Some file systems may not be capable of handling large number of
files in a single directory; you may need to create sub directories under the
directory specified by plsql_native_library_dir for storing
the native compilation generated shared libraries.
If you use a production quality file system (e.g Veritas) you may not need
to create sub directories. However, if you are using a vanilla file system, it
may not be able to gracefully handle a large number of files in a single
directory. For Oracle Applications which has about 70,000 PL/SQL objects, when
using a vanilla file system, we use about 500 sub-directories.
The default value for this parameter is 0. In order to instruct Oracle to
distribute the shared libraries under the various sub-directories (rather than
storing all the shared libraries in the single directory specified by
plsql_native_library_dir), set the
plsql_native_library_subdir_count parameter to the number of
sub-directories you intend to create.
For example, to use 500 sub-directories, add the following
line to your initialization parameter file:
plsql_native_library_subdir_count=500
You must then create 500 sub-directories (under the directory specified
by the plsql_native_library_dir parameter) with
exactly the names d0, d1, d2, .., d498, d499.
Back to top
plsql_code_type
parameter
The parameter plsql_code_type determines whether PL/SQL code is
natively compiled or interpreted. The default setting is INTERPRETED. To enable
PL/SQL native compilation, set the value of plsql_code_type to NATIVE.
If you compile the whole database as NATIVE, Oracle Corporation recommends
that you set plsql_code_type at the system level or in the initialization
parameter file.
Use the following syntax to set this parameter:
- For native compilation mode:
alter session set plsql_code_type='NATIVE'
or,
alter system set plsql_code_type='NATIVE'
- For interpreted mode:
alter session set plsql_code_type='INTERPRETED'
or,
alter system set plsql_code_type='INTERPRETED'
Back to top
Format of the spnc_commands File
The spnc_commands file, in the $ORACLE_HOME/plsql
directory, contains the templates for the commands to compile and link each
program. Some special names such as %(src) are predefined, and are replaced by
the corresponding filename. The variable $(ORACLE_HOME) is also
automatically replaced by the location of the Oracle home directory. You can
include comment lines, starting with a # character. The file
contains comments that explain all the special notation.
The spnc_commands file contains a predefined path for the C compiler,
depending on the particular operating system. (One specific compiler is
supported on each operating system.) In most cases, you should not need to
change this path, but you might if you the system administrator has installed
it in another location.
This approach means than (unlike in version 9.0.1 and version 9.2.0) there
is no dependency on a make utility.
Back to top
In which dictionary table are the shared
libraries generated by native compilation stored?
The shared libraries generated by native compilation are stored in the
database as BLOBs in the ncomp_dll$ dictionary table.
SQL> connect / as sysdba;
Connected.
SQL> describe ncomp_dll$;
Name Null? Type
------------ -------------- --------
OBJ# NOT NULL NUMBER
VERSION NUMBER
DLL BLOB
DLLNAME RAW(1024)
Back to top
What happens to the shared library on the filesystem
when I drop a NATIVE unit?
Up until 9.2.0, nothing. The shared library was not garbage collected.
In version 10.1.0, when a natively compiled unit is either dropped or recompiled in
interpreted mode, the shared library is deleted both from the
ncomp_dll$ dictionary table as well as from the the file system
location specified by the plsql_native_library_dir parameter. In
case of RAC configuration, the shared library is deleted from each instance's
plsql_native_library_dir location.
Back to top
How do I change plsql_native_library_dir
If you need to change the value for this parameter, the recommend steps are:
- Shut down the DB instance
- Change plsql_native_library_dir setting in the initialization
parameter file to point to the new location.
- Restart the DB instance. Oracle will automatically extract the shared
libraries into this new location on demand.
Note 1: Although this parameter can be changed via the "alter system.. "
command, Oracle recommends against it.
Note 2: Once the above steps have been followed, it is now safe to
delete the old directory corresponding to the prior setting
of plsql_native_library_dir. Oracle will not automatically delete
the shared libraries from the old location.
Back to top
Are there any other circumstances where I need to
delete a shared library by hand?
No.
The only exception is if you want to change the setting for
plsql_native_library_dir. Follow the steps
described earlier to change plsql_native_library_dir. The
shared libraries can then be deleted from the old location.
Back to top
What if I delete a shared library by
mistake?
This could cause undesirable internal errors and problems. The suggested
remedy is to shutdown and startup the instance. Oracle will automatically
extract the shared library on demand from the ncomp_dll$
dictionary table.
Back to top
Does Oracle Corporation recommend mixing NATIVE and INTERPRETED units?
Mixing is supported and never results in wrong behavior. However, there's a
cost when a NATIVE unit calls an INTERPRETED one. You might compromise some of
your potential performance improvement if NATIVE units frequently call
INTERPRETED units.
If time to compile all modules natively into shared libraries is an issue
one option to consider is to compile specifications for packages and types in
interpreted mode and all the other types of PL/SQL units (package
bodies, type bodies, procedures, functions and triggers) in native
mode. Since specifications generally do not have much executable code, you
won't be losing much in terms of run-time performance either.
Back to top
Do I need to regenerate the native
shared libraries on an OS upgrade?
Provided that you have already established that Oracle Corp supports this
type of OS upgrade without needing to regenerate the ordinary Oracle
executables, then the shared libraries that arise from PL/SQL NATIVE
compilation will also be viable without needing regeneration.
Back to top
Can I use native mode to save
time during application deployment (by shipping pre-generated NCOMP shared
libraries)?
No! You cannot do this even if the shared libraries are generated on the same
platform as the eventual deployment environment. You cannot do this with
MCode in interpreted mode either.
This is for reasons unrelated to the compilation mode. Installation of
a PL/SQL based application in a database requires the PL/SQL modules to be
loaded and compiled in that database so that all the external references are
correctly resolved.
Back to top
Test driving native compilation: Simple Test
- Create a directory for storing the shared libraries generated by native
compilation and set the plsql_native_library_dir
parameter in the initialization parameter file to point to that directory path.
For example, you will need to add something like this to your initialization
parameter file:
plsql_native_library_dir=/home/kmuthukk/oracle10g/dbs/ncomp_libraries
- Optionally set up plsql_native_library_subdir_count in the initialization parameter file and create the subdirectories.
- Ensure that the OS path of the C compiler (and if applicable, the linker)
used in the spnc_commands file
is correct.
- System parameters Sanity Check: plsql_native_library_dir MUST be specified. plsql_native_library_subdir_count is optional and may be left at 0 (if you are not planning to use sub-directories based
scheme). It is best if these parameters are specified in the
initialization parameter file.
SQL> show parameters plsql_native
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
plsql_native_library_dir string /home/kmuthukk/oracle10g/dbs/ncomp_libraries
plsql_native_library_subdir_count integer 0
- Natively Compiling a PL/SQL module
- To load and compile new modules in native mode you must
set the plsql_code_type
parameter to NATIVE.
For example, try the following in SQL*Plus:
connect scott/tiger
alter session set plsql_code_type='NATIVE';
create or replace procedure my_test is
begin
dbms_output.put_line('hello world');
end;
/
show errors;
set serveroutput on;
execute my_test;
Verification Steps:
- Take a peek at the location specified
by plsql_native_library_dir. You should find a new
shared library corresponding to MY_TEST procedure.
On Solaris, the DLL may have a name like
MY_TEST__SCOTT__P__54765.so.
[To read more about shared library naming conventions, click here.]
- Also, make sure that the plsql_code_type setting
for this module is indeed NATIVE by issuing the following query:
select name, type, plsql_code_type
from user_plsql_object_settings
where name = 'MY_TEST';
- If you want to manually compile specific already loaded modules
native, you can use the "alter ... compile .. "
statements.
Suppose you have a package MYPKG whose specification and body
are compiled interpreted. Now, if you want to natively compile just its body,
then issue the following command:
alter package MYPKG compile body plsql_code_type=native reuse settings
The reuse settings clause above indicates that
the compiler should preserve all the prior settings for the unit,
except for the ones which have been explicitly overridden (such
as the setting for plsql_code_type setting in the
example above).
If the body clause is dropped from the above
statement, as in...
alter package MYPKG compile plsql_code_type=native reuse settings
... then both the specification and body will be recompiled in
native mode. Note however that recompiling a specification
triggers a invalidation of other modules that depend on the specification.
Back to top
Natively compiling all PL/SQL units in the database
Before attempting to natively compile all PL/SQL units in the database, try it out
on a simple test case as described in the previous
section. This will help ensure that your setup is ok for native compilation.
- Operating System File Descriptor Limit
Two SQL*Plus scripts (dbmsupgnv.sql and utlrp.sql)
on the $ORACLE_HOME/rdbms/admin directory are used to recompile
all PL/SQL modules in native mode. They use parallel jobs
(depending on the number of available CPUs). In such situations, many jobs
concurrently generate C files and attempt to compile them. It is therefore
important that the OS limits on max number of file descriptors isn't set
too low.
For example, on my Solaris machine:
% ulimit -a
time(seconds) unlimited
file(blocks) unlimited
data(kbytes) 2097148
stack(kbytes) 8192
coredump(blocks) 3
nofiles(descriptors) 64
vmemory(kbytes) unlimited
Note the value of 64 for max number of file descriptors. This is too low in
production environments if you have many jobs running native compilation in
parallel. You may want to check what the limits are on your machine and
increase them. For example:
On Solaris, the steps are to edit the
/etc/system file to have something like:
set rlim_fd_max=4096
set rlim_fd_cur=1024
On HP-UX, the corresponding parameters are in the
/stand/system file.
maxfiles 2048
maxfiles_lim 2048
- System Table Space
Since the master copy of the DLLs is stored in dictionary
tables, you may need more SYSTEM table space than before. If
you run into errors with space limits on the SYSTEM table
space, you would need to do something like..
alter tablespace system
add datafile '/home/kmuthukk/oracle10g/dbs/mydata10.dbf'
size 500 m;
.. or set up autoextend on the datafile.
- Recompiling all modules native (dbmsupgnv.sql and utlrp.sql)
- Shutdown all of the Application services including the Forms Processes,
Web Servers, Reports Servers, and Concurrent Manager Servers. After shutting
down all of the Application services, ensure that all of the connections to the
database have been terminated.
- Shutdown the TNS listener of the database to ensure that no new
connections are made.
- Shutdown the database (in normal or immediate mode).
- Check that you have already set the
plsql_native_library_dir in the initialization paramater file.
If not, see steps described in the previous
section.
- Set plsql_code_type to NATIVE in the initialization
parameter file.
plsql_code_type=NATIVE
- Startup the database in UPGRADE mode (using STARTUP UPGRADE or ALTER
DATABASE OPEN UPGRADE).
- Run the following query to obtain the number of invalid objects. This
value will be used later as a comparison to ensure that the recompilation did
not produce additional invalid objects due to native compilation failures.
Select count(*)
From all_objects
Where status='INVALID';
- The following query should tell you how many objects are compiled
native versus interpreted.
SELECT plsql_code_type, count(*)
FROM dba_plsql_object_settings
GROUP BY plsql_code_type;
You might see some objects with a NULL plsql_code_type.
These are special internal objects and may be ignored.
- cd (change directory) to $ORACLE_HOME/rdbms/admin.
- Run the $ORACLE_HOME/rdbms/admin/dbmsupgnv.sql (as SYS).
Note 1: dbmsupgnv.sql invalidates all PL/SQL modules and updates
dictionary tables to change their plsql_code_type settings to NATIVE.
This phase must be done when no other activity is happening on the database;
hence, we require that the DB be started in UPGRADE mode during dbmsupgnv.sql.
Note 2: If you are upgrading from a lower version of database to
higher version of database (for example to Oracle Database 10g) then you
must first run the upgrade scripts and then run the dbmsupgnv.sql. For
example, if you are upgrading from version 9.2.0.3 to 10.1.0. First run the upgrade scripts
(u0902000.sql) and shutdown the database and run the
dbmsupgnv.sql script.
- Commit the changes after running dbmsupgnv.sql
SQL> commit;
- Shutdown the DB.
- Restart DB in normal mode.
- Run $ORACLE_HOME/rdbms/admin/utlrp.sql script (as SYS).
This step will recompile all the PL/SQL modules. [During this process, you
may want to periodically peek in the directory specified by the
plsql_native_library_dir to ensure that the new shared libraries
are indeed getting created by the compilation process.]
Note: This step is restartable. If for any reason this step is
abnormally terminated, you may simply restart this step (i.e. rerun
the utlrp.sql script). It will recompile any remaining
invalid PL/SQL modules.
- After the compilation completes successfully, you should verify that the
number of invalid objects is less than or equal to the number of invalid
objects prior to the recompilation. You can use the following query to
obtain the number of invalid objects.
Select count(*)
From all_objects
Where status='INVALID';
Also run the following query to make sure you have no more
interpreted modules left:
SELECT plsql_code_type, count(*)
FROM dba_plsql_object_settings
GROUP BY plsql_code_type;