SQLcl - SQL*Plus with Benefits plus Calling PLSQL from SQL since 12c Erik van Roon OUG Scotland 2019
SQLcl - SQL*Plus with Benefitsplus
Calling PLSQL from SQL since 12c
Erik van Roon
OUG Scotland 2019
Who Am I?
• Erik van Roon
• Originally analyst of microbiology and biochemistry
• Oracle developer since 1995, self-employed since 2009
• Most of my work takes place inside the database
• *Playing* with APEX since 2008
• Did several successful major datamigration projects
: [email protected]: www.evrocs.nl : @evrocs_nl
SQLcl(SQL*Plus with benefits)
What is SQLcl?
• a command line Interface like SQL*Plus
• Built in Java by the SQL-Developer team
• Built around the SQLDev Java library for executing SQL
• Runs anywhere a JRE is available(Windows, Linux, Mac,…)
Q: Will it replace SQL*Plus?A: No! “SQL*plus will always exist alongside SQLcl”
How do you get SQLcl?
• Included in SQL Developer
• So, also in DBMS installation(Recent versions)
• Available from Oracle Software Downloadshttp://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html
Only place it’s missing now is the Oracle Client Software
Installation
Pay attention
This is really hard
• Go to the download pagehttp://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html
• Login with your OTN account
• Accept the license agreement
• Click 'Download’
• Save the zip file
• Unzip the zipfile
• Multiple concurrent versions are possiblejust unzip to different directories
• No need for
–Oracle client installation
– tnsnames.oraThough you can use one of course
– JDK (Though you do need a JRE >= 1.8)
Release notes 19,1 say“Java versions 9 and 10 are not yet supported”
Jeff Smith blog (April 29 2019) says“You can already use Java 11 for Oracle REST Data Services and SQLcl”
Disadvantages?
Bugs
Example: Since 18.2 serveroutput with “format wrapped” causes
extra empty lines in output when script has comments
However:
• SQLcl is frequently updated
• SQL*Plus has bugs too(e.g. unpatched version in 12.2 ignores SQLPATH)
SQL*Plus SQLclScript
Disadvantages?
Startup is slower dan sqlplus
However:• On average computer
difference not enough to worry about• On my laptop:
Start Sql*Plus < 1 secStart SQLcl 3 - 4 sec
Disadvantages?
Supports a lot but not everything SqlPlus
19.1, "SQL*Plus List of Unsupported Commands and Features":- REPHEADER- REPFOOTER
“Column” accepts entire SqlPlus syntax, But apart from “new_value” everything is ignored.
SqlPlus SQLcl
Find the differences
Help
Run help to get information on (almost) all functionality
The asterisks indicate which are unique for sqlcl
Help is (really) good, but not perfect:• Modifiers for Bridge not mentioned in help
• Seterrorl is not a command. “help seterrorl” leads to help for
“set errorlogging …”which is missing in “help set” :-b
Command Completion
Start typing a statement and hit [Tab]
‘Hits’ are displayed and if all hits have a common start (in this case EVROCS_), it is already filled in…
➢ Query needs to be ‘sensible’:
SELECT FROM EVR [Tab]
Won’t work
Command Completion, the motion picture
History
show history Shows current history settings, *not* the history itself
history will show a list of executed statements, 1 statement per line
history full list of executed statements, as entered (also multiline)
history usage same as 'history' but also displays number of executions
history time same as 'history' but also displays execution time
history clear erases the entire history buffer
history (entry number) loads statement with given entry number into the sqlcl buffer
Also: just browse through your history using arrow-up & arrow-downPer statement!! Not per entered line as in sqlplus.
History
- is enabled (haven't found a way to disable)- Doesn't store duplicates of statements, each unique statement is stored only once- Stores multiline statements as one entry, not individual lines- stores a maximum of 100 statements, increase/decrease with for example:
set history limit 500set history limit default to return to default behavior
- Doesn't store failed queries, so no pollution, but also no correcting of typos. Toggle this behavior with
set history fails 10 to have a maximum of 10 failed statements in historyset history nofails to go back to default behavior
- Does not store show, history, connect and set commands. Change this list with for example:
set history blacklist show,history,connect,set,commit,rollback
History
Warning:
EXEC statements are expanded to plsql blocks in history
Exec ended with semicolon (don’t!)leads to invalid statement in history due to extra semicolon
command line editing
Edit complete statements (not just lines) without external editor
• Use up & down keys to get to statement of interest in history
• Use Left key to enter editing mode
• Modify statement however you want
• Hit CTRL-R to run the modified statement
command line editing, the motion picture
Sqlformat
formats the output of all following sql statements
set sqlformat [format]
All formats are also available as comments in a query
(like they are in SQLDev):
select /*csv*/ * from user_tables;
Sqlformat - Formats
• csv Output as comma separated values
• json Output as json
• fixed Fixed width columns, double-quoted values
• html Output as html
• insert Output as insert statements
• default Clears any set sqlformat
• xml Output as xml
• loader Pipe (|) delimited values
• delimited Like csv, but separator and delimiters can be defined
• ansiconsole Pretty output (see later)
Sqlformat – delimited
Returns character separated values.
Separator and delimiters can be defined in parametersSet sqlformat delimited [delimiter [encloser-left [encloser-right]]]
• Delimiter can not be a non-printable character (like Tab)
• Enclosers can not be empty, defaults to double quote
Sqlformat – Ansiconsole
Output is formatted more readable
Column widths are based on actual data and headers
Sqlformat – Ansiconsole
Some enhancements possible:
• Data containing EndOfLine not handled correctly yet
• If statement edited and run with [enter], header starts at last line of statement
Sqlformat – Ansiconsole Number format
Set a default format for your number columns
set sqlformat ansiconsole [format]
Format as in Java (link to webpage is in help text)
Sqlformat – Ansiconsole Data Highlight
Highlight data returned by queries
Define rules in a json file like:
{"highlights":
[
{"type":"startWith" ,"test":"ERO" ,"color":"INTENSITY_BOLD,YELLOW"},
{"type":"endWith" ,"test":"GTT" ,"color":"BLUE" },
{"type":"contains" ,"test":"SNAPSHOT" ,"color":"CYAN" },
{"type":"exact" ,"test":"CUSTOMERS" ,"color":"GREEN" },
{"type":"regex" ,"test":".*[0-9].*" ,"color":"MAGENTA" }
]
}
Sqlformat – Ansiconsole Data Highlight
Does *not* work in Windows ‘DosBox’/cmd-window
Does work in alternativesLike ConEMU
Apex
Command Apex lists all applications
Apex export
Help just says: apex export <app id> - Exports the application which could be combined
with spool for writing to a file
But typing in rubbish like apex export 0 alkjsdhfkjh
Shows there is more
Info(rmation)
Info / Information shows information about most object types
For a table it shows regular 'desc' information plus:
• table analysis information (last analyzed, row count, ...)
• table and column comments
• column default values
• indexes
• foreign key constraints
Info(rmation)
Info+
Info+ (currently there is no Information+)
When used for tables the column comments are replaced by some statistics
• low value
• high value
• number of distinct values
• type of histogram
Info+
Alias
alias show list of currently loaded aliases
alias list same as "alias" but includes alias descriptions
alias list MyAlias Shows the statement that MyAlias is an alias for
alias MyAlias=(pl)sql Defines alias MyAlias for some sql or plsql
alias MyAlias=@script Defines alias MyAlias for some sql script
alias drop MyAlias Removes alias MyAlias from memory
alias save [filename] Saves ALL currently loaded aliases to filenamedefault file is %APPDATA%\sqlcl\aliases.xml
alias load [filename] Loads aliases from filenamedefault file is %APPDATA%\sqlcl\aliases.xmlAppends to already loaded aliases, overwrites already existing ones
Assign a user-defined name to sql, plsql and scripts
Unless ‘save’ is used, alias is for the duration of the SQLcl session
Alias - Example
PLSQL block, including bind variables
Alias - Case
Watch out aliases are case-sensitive
Alias – Host command
Even host commands can be aliasedProvided you end them with a semicolon
Working directory
It's the little things that make life good
PWD (Print Working Directory)• displays the current working directory, like the linux/unix pwd command
• saves user one keystroke (pwd instead of !pwd or $dir)
• saves windows users a lot of unwanted output compared to $dir
CD (Change Directory)• changes the working directory while inside SQLcl
• Even to other disk, without the usual dos /d parameter
• No more need to exit, change directory and start a new commandline
Files
Find filenameIs supposed to list all occurrences of filename in the SQLPATH
But lists all in:
• SQLPATH
• Working directory
• All subdirs of working dir
• All subdirs of sqlpath dirs
No wildcards allowed
Which filenamedisplays the pathname of the script that will be executed if called with @filename
DDL
Basically just shorthand for dbms_metadata.get_ddl
ddl object_name [object_type] [save filename]
Behavior can be altered with dbms_metadata like:exec dbms_metadata.set_transform_param
(dbms_metadata.session_transform, 'CONSTRAINTS_AS_ALTER', true);
exec dbms_metadata.set_transform_param
(dbms_metadata.session_transform, 'SEGMENT_ATTRIBUTES' , false);
If used often: make aliases for such transforms.
DDL
Bridge
Bridge gets data from a remote connection into a local table without needing a database link
Similar to sqlplus command "copy".
bridge targettable as "jdbcURL" (query)[modifier];
jdbcURL : jdbc:oracle:thin:username/password@host:port/servicename
e.g. : jdbc:oracle:thin:ero/ero@localhost:1521/evrocs
Targettable is created if it does not exist.
Bridge – modifier
The modifier is not in the help yet!!!
(= no modifier) Always do create target table. Ora-00955 if it already exists
replace Drop target table if it exists, then re-create it and add the data
append Add the data of the query to possibly existing data in target table
truncate Truncate the target table before adding the data
skip If table exists: it does nothing (reports "table already exists, inserted 0 rows")
If table doesn’t exist: will create it and add the data
Modifier HAS (!!) to be directly after closing bracket after query
Repeat
Repeat runs the statement in the buffer
For a requested number of times With a requested wait time between executions
repeat number_of_times seconds_between_executions
The wait time can not be more then 120 seconds
Repeat – The Motion Picture
TIP
SQLcl uses same SQLPATH environment variable as SqlPlus
So• will execute the same (g)login.sql
So what?• sqlcl-specific stuff in login.sql will cause
errors when starting sqlplus• sqlplus-specific stuff in login.sql that is not
(yet/fully) supported in sqlcl will cause errors when starting sqlcl
But: easily fixed….
1. All common settings in x:\login\common_login.sql
Fix common SQLPATH
2. Create x:\login\PLUS\login.sql• All SQLPLUS specific settings• @@..\common_login.sql
3. Create x:\login\CL\login.sql• All SQLCL specific settings• @@..\common_login.sql
4. Create batchfiles sp.bat & sc.bat• Add the login directory to SQLPATH• Run the executable passing all parameters
Fix common SQLPATH
x:\login\common_login.sql x:\login\PLUS\login.sql
x:\login\CL\login.sql
sp.bat sc.bat
TIP
In SQLPLUS language of messages controlled by NLS_LANG
In SQLcl the language is determined by OS language
To change this, add to previously mentioned batch file:
set JAVA_TOOL_OPTIONS=-Duser.language=en -Duser.region=US
Replace ‘en’ and ‘US’ as desired
TIP
By default error messages show more than in sqlplus
If you don’t like that:
set classic on
TIP
Watch out:
set feedback off
Also suppresses all error messages
Release notes of 18.3 say:
But still present in 19.1
Calling userdefined functions
from SQL queries
got faster in Oracle 12c
The problem:
– SQL and PLSQL have their own engines
–Calling one from the other introduces context switches
–Doing so often has a performance impact
Speeding up SQL calls from PLSQL involves:
–Doing as little individual SQL statements as possible
–Doing Bulk Operations
• Bulk Collect
• Forall
Speeding up PLSQL calls from SQL involves:
Pre 12c: Do it as little as possible
i.e. Try to do it in pure SQL
12c and beyond:
–defining plsql functions in Subquery Factoring (the with clause)
–defining functions using PRAGMA UDF
PLSQL in Subquery Factoring
Example of a function in the with clause:withfunction digit_sum(pi_integer in integer)return integeris
c_as_string constant varchar2(15) := to_char(pi_integer,'fm999999999999999');l_result integer := 0;
beginfor i_pos in 1 .. length(c_as_string)loop
l_result := l_result + to_number(substr(c_as_string, i_pos, 1));end loop;return (l_result);
end;--select object_id "Object ID", digit_sum (object_id) "Sum Of Digits"from user_objectsfetch first 4 rows only/
Must be “/”, not “;” in SQL*Plus and SQLcl
PLSQL in Subquery Factoring
Result:
Warning:
If a function is declared right there in the querythe mistake is easily made to think it’s part of the query
However:
This plsql is NOT part of the read consistencyTrue for ANY PLSQL called from SQL
If the PLSQL is not defined in the top-level query, but for example:
– In any subquery
– In the query of an “insert into .. select from ..”
– In the “using()” query of a merge statement
We need to ‘warn’ the compiler that it will run into PLSQL:
Use the hint:
/*+ WITH_PLSQL */
For example PLSQL defined in select of an insert:insertinto my_table (col1, col2)withfunction do_somethingreturn ....isbeginreturn (...);
end;select source_data, do_somethingfrom other_table/
will result in ORA-32034: unsupported use of WITH clause
insert --+ with_plsqlinto my_table (col1, col2)with function do_something return .... is begin return (...);
end; select source_data , do_something from other_table /
will be successful
Syntax errors can lead to pretty useless error messages.Often the message will just be:
ERROR at line ###: ORA-00905: missing keyword
where the line number is the line where the function begins
Advise: develop the PLSQL in an anonymous block until syntactically correct, before putting it into the with-clause
Procedures can also be defined in the With-clause!But can obviously only be executed from other plsql in with clause, not the query.
with
procedure proc1(pio_1 in out number)
isbeginpio_1 := power(pio_1 , 2);dbms_output.put_line ('Squared number '||to_char(pio_1));
end proc1;--
function func1(pi_1 in integer)return numberisl_value_1 number := pi_1;
begin
proc1 (pio_1 => l_value_1);
return (l_value_1);end func1;
select level value
, func1 (pi_1 => level) calculated_value
from dualconnect by level <= 5/
PLSQL in Subquery Factoring
Unfortunately, Function Result Cache can not be used
with
function f (p in integer)
return varchar2
result_cache
as
begin
return (p);
end;
--
select function_input
, f (function_input) function_output
from (select mod(level,2) function_input
from dual
connect by level <= 4
)
/
The function *can* be declared deterministic without error messages, however .....
In 12.1No error messages, But deterministic is ignored
In 12.2 and 18:Sometimes it works
Sometimes it's ignoredAt least one case gives wrong results
In 19 (livesql: https://livesql.oracle.com):Back to 12.1 behavior: always ignore deterministic
So, Best bet: Don’t use deterministic with this
Behavior as expected in 12.2 & 18withfunction f (p in integer)
return integerdeterministicasbegindbms_output.put_line ('Executed for value '||p);return (p);
end;--select function_input, f (function_input) function_outputfrom (select level function_input
from dualconnect by level <= 4union allselect level function_inputfrom dualconnect by level <= 4
)/
Behavior *not* as expected in 12.2 & 18
withfunction f (p in integer)
return varchar2deterministicasbegindbms_output.put_line ('Executed for value '||p);return (p);
end;--select function_input, f (function_input) function_outputfrom (select level function_input
from dualconnect by level <= 4union allselect level function_inputfrom dualconnect by level <= 4
)/
Example of *wrong* deterministic results in 12.2 & 18
with
function f (p in integer)
return integer
deterministic
as
begin
dbms_output.put_line
('Executed for value '||p);
return (p);
end;
--
select mod(level,2) function_input
, f (mod(level,2)) function_output
from dual
connect by level <= 4
/
In 19 (LiveSql) correct results, but deterministic ignored
Scalar Subquery Caching *does* work in 12.1Not in 12.2, 18, 19
withfunction f (p in integer)return varchar2asbegindbms_output.put_line ('Executed for value '||p);return (p);
end;select function_input, (select f (function_input)
from dual) function_output
from (select level function_inputfrom dualconnect by level <= 4union allselect level function_inputfrom dualconnect by level <= 4)
/
12,1
12,2
There’s a bug, causing ora-600 in *a very specific case*(Bug 22654079)
If:
1. You have a merge statement
2. AND there's plsql in the with-clause of the 'using' query
3. AND the statement uses bind variables
THEN:
ORA-03113: end-of-file on communication channel
Example of bug 22654079
merge /*+ with_plsql */into ero_test_merge_bug tgtusing (with
function f (p in integer)return integerisbeginreturn p * 10;
end;--select id, f (id) valuefrom ero_test_merge_bugwhere id = :my_id
) srcon (tgt.id = src.id)when matchedthenupdate set tgt.value = src.value
when not matchedtheninsert values (src.id, src.value)
/
PLSQL in the with clause is not supported by PLSQL (yet?)
Declaring a cursor with such a query leads, once again to
"ORA-00905: missing keyword“
Work-around: dynamic sql *does* work
But: ..............................................
If already in plsql anyway, why not declare the function separately with pragma udf?
Wait! So we have an alternative?
Of course!
There's the possibility to add a
Pragma UDF
to a standalone or packaged function.
Instructs the compiler that the function will be used within SQL.
Documentation says:
"...which might improve its performance"
How do we apply this?
create or replace function blabla
return ...
is
pragma udf;
begin
....
return ...
end;
/
Advantages compared to with-clause functions
– no need for with_plsql hint in any situation
– debugging the plsql is easier: syntax errors give ‘usual’ messages
– function result cache can be used
– Deterministic can be used, behaves like deterministic function in with clause, except that the query that gives wrong results when using a deterministic function in with-clause, now works correct
– Scalar Subquery Caching also works
– Can be used without problem in merge statements containing bind variables
– reuse of function in other queries possible
Disadvantage compared to with-clause functions
– You need to create an object (function/package) in the database.
You may not want to do that (e.g. for a script in your toolkit for daily development/dba work)
You may not be allowed to do that (e.g. for a check script you run on different databases, among which Production)
– Performance gain (as we will see later) is hard to predict
How do these two features affect performance?
Measure runtime of test executions:
– For combinations of input parameter- & return datatypes
– Run each test 11 timesignore result of first runcalculate average and standard deviation for the others
– Flush the shared pool after each (11 executions of a) test
– Tests were executed on a table of 5 million rows
Plsql_optimize_level:
Tests have been run for all levels (0,1,2,3).
No significant differences in performance for any specific test noticed when running with either of the optimize levels.
Following results were obtained with plsql_optimize_level 2
The following tests have been executed:
Test name Description
PLAIN SQL Sql statement without plsql
REGULAR Sql statement calling a regular database function
WITH Sql statement calling a function in the with clause
UDF Sql statement calling a UDF database function
WITH WRAPS REGULAR Function in the with clause calls a regular DB function
WITH WRAPS UDF Function in the with clause calls a UDF DB function
UDF WRAPS REGULAR Sql calls UDF DB function which calls regular DB function
REGULAR WRAPS REGULAR Sql calls regular DB function which calls a regular DB function
UDF WRAPS UDF Sql calls UDF DB function which calls UDF DB function
REGULAR WRAPS UDF Sql calls regular DB function which calls UDF DB function
Test : Regular PLSQL (= Baseline)
Parameter Return Runtime Std Dev 95% confidence Ratio
Number Number 5,681 0,090 0,056 100
Varchar2 Number 6,856 0,049 0,030 100
Date Number 7,124 0,246 0,152 100
Number Varchar2 5,805 0,050 0,031 100
Varchar2 Varchar2 7,127 0,117 0,073 100
Date Varchar2 7,224 0,093 0,058 100
Number Date 10,201 0,164 0,102 100
Varchar2 Date 10,549 0,367 0,227 100
Date Date 10,254 0,243 0,151 100
Binary Float Binary Float 7,173 0,064 0,040 100
Binary Double Binary Double 7,142 0,125 0,077 100
Test : Plain SQL (No PLSQL Calls)
Parameter Return Runtime Std Dev 95% confidence Ratio
Number Number 1,394 0,013 0,008 25
Varchar2 Number 1,372 0,017 0,011 20
Date Number 1,369 0,036 0,022 19
Number Varchar2 1,415 0,025 0,015 24
Varchar2 Varchar2 1,434 0,016 0,010 20
Date Varchar2 1,392 0,033 0,020 19
Number Date 1,549 0,021 0,013 15
Varchar2 Date 1,512 0,009 0,006 14
Date Date 1,454 0,019 0,012 14
Binary Float Binary Float 2,466 0,034 0,021 34
Binary Double Binary Double 2,429 0,028 0,017 34
Test : PLSQL in With Clause
Parameter Return Runtime Std Dev 95% confidence Ratio
Number Number 2,387 0,138 0,086 42
Varchar2 Number 2,265 0,017 0,011 33
Date Number 2,315 0,015 0,009 32
Number Varchar2 2,728 0,050 0,031 47
Varchar2 Varchar2 2,782 0,055 0,034 39
Date Varchar2 2,755 0,035 0,022 38
Number Date 5,051 0,061 0,038 50
Varchar2 Date 5,026 0,153 0,095 48
Date Date 4,917 0,083 0,051 48
Binary Float Binary Float 2,358 0,033 0,020 33
Binary Double Binary Double 2,729 0,697 0,432 38
Test : Database Function Using Pragma UDF
Parameter Return Runtime Std Dev 95% confidence Ratio
Number Number 2,095 0,010 0,006 37
Varchar2 Number 6,913 0,033 0,020 101
Date Number 6,973 0,054 0,033 98
Number Varchar2 2,232 0,012 0,007 38
Varchar2 Varchar2 7,375 0,082 0,051 103
Date Varchar2 7,384 0,135 0,084 102
Number Date 10,152 0,076 0,047 100
Varchar2 Date 10,248 0,069 0,043 97
Date Date 9,985 0,064 0,040 97
Binary Float Binary Float 2,131 0,067 0,042 30
Binary Double Binary Double 2,100 0,038 0,024 29
Test : With clause calling a regular function
Parameter Return Runtime Std Dev 95% confidence Ratio
Number Number 3,114 0,022 0,014 55
Varchar2 Number 3,111 0,020 0,012 45
Date Number 5,516 0,026 0,016 77
Number Varchar2 3,480 0,048 0,030 60
Varchar2 Varchar2 3,623 0,036 0,022 51
Date Varchar2 6,006 0,115 0,071 83
Number Date 5,834 0,210 0,130 57
Varchar2 Date 5,682 0,058 0,036 54
Date Date 7,493 0,052 0,032 73
Binary Float Binary Float 3,236 0,043 0,027 45
Binary Double Binary Double 4,541 1,160 0,719 64
Test : With clause calling a UDF function
Parameter Return Runtime Std Dev 95% confidence Ratio
Number Number 3,106 0,024 0,015 55
Varchar2 Number 3,150 0,008 0,005 46
Date Number 5,796 0,088 0,055 81
Number Varchar2 3,478 0,050 0,031 60
Varchar2 Varchar2 3,790 0,330 0,205 53
Date Varchar2 6,179 0,072 0,045 86
Number Date 5,972 0,084 0,052 59
Varchar2 Date 5,922 0,052 0,032 56
Date Date 7,610 0,079 0,049 74
Binary Float Binary Float 3,148 0,041 0,025 44
Binary Double Binary Double 3,910 0,655 0,406 55
Test : a regular function calling a regular function
Parameter Return Runtime Std Dev 95% confidence Ratio
Number Number 6,563 0,084 0,052 116
Varchar2 Number 7,855 0,051 0,032 115
Date Number 10,930 0,102 0,063 153
Number Varchar2 7,141 0,052 0,032 123
Varchar2 Varchar2 8,501 0,051 0,032 119
Date Varchar2 11,432 0,247 0,153 158
Number Date 11,065 0,239 0,148 108
Varchar2 Date 11,610 0,106 0,066 110
Date Date 13,117 0,125 0,077 128
Binary Float Binary Float 8,143 0,078 0,048 114
Binary Double Binary Double 8,311 0,083 0,051 116
Test : a regular function calling a UDF function
Parameter Return Runtime Std Dev 95% confidence Ratio
Number Number 6,461 0,066 0,041 114
Varchar2 Number 7,974 0,064 0,040 116
Date Number 10,809 0,046 0,029 152
Number Varchar2 7,075 0,068 0,042 122
Varchar2 Varchar2 8,837 0,428 0,265 124
Date Varchar2 11,670 0,112 0,069 162
Number Date 11,106 0,092 0,057 109
Varchar2 Date 11,394 0,180 0,112 108
Date Date 13,647 0,444 0,275 133
Binary Float Binary Float 8,168 0,063 0,039 114
Binary Double Binary Double 8,363 0,162 0,100 117
Test : a UDF function Calling a regular function
Parameter Return Runtime Std Dev 95% confidence Ratio
Number Number 2,870 0,019 0,012 51
Varchar2 Number 8,191 0,246 0,152 119
Date Number 10,921 0,130 0,081 153
Number Varchar2 3,250 0,040 0,025 56
Varchar2 Varchar2 8,497 0,087 0,054 119
Date Varchar2 11,412 0,093 0,058 158
Number Date 11,436 0,223 0,138 112
Varchar2 Date 11,614 0,127 0,079 110
Date Date 13,293 0,197 0,122 130
Binary Float Binary Float 2,827 0,026 0,016 39
Binary Double Binary Double 3,035 0,052 0,032 42
Test : a UDF function calling a UDF function
Parameter Return Runtime Std Dev 95% confidence Ratio
Number Number 3,007 0,025 0,015 53
Varchar2 Number 8,017 0,087 0,054 117
Date Number 10,897 0,113 0,070 153
Number Varchar2 3,221 0,033 0,020 55
Varchar2 Varchar2 8,635 0,108 0,067 121
Date Varchar2 11,517 0,098 0,061 159
Number Date 11,368 0,145 0,090 111
Varchar2 Date 11,513 0,125 0,077 109
Date Date 13,234 0,099 0,061 129
Binary Float Binary Float 2,938 0,029 0,018 41
Binary Double Binary Double 2,990 0,039 0,024 42
Conclusions from these performance tests
These tests have NOT been run with YOUR real life functions / queriesThese tests have NOT been run on YOUR hardwareThese tests have NOT been run on YOUR version of YOUR database with YOUR patches
Conclusions from these performance tests
Plain SQL without PLSQL • No surprise:
Plain SQL without PLSQL is ‘always’ fastest
Datatypes • Parameter- and (mainly) Return datatypes have an impact on runtime
Even with regular functions:returning number takes half the runtime of returning dates
Conclusions from these performance tests
SQL, calling UDF database function • Faster than calling regular database function
but only for specific datatype combinations
Mainly when handling numeric datatypes
• If it is faster than regular, it’s also a bit faster then a function in the with clause (~10-20%)
Functions in the with clause• Appear to always be faster than regular functions
Regardless of used datatypes
Conclusions from these performance tests
Function in the with clause that calls a database function• Will be faster than calling the database function regularly
It makes no real difference if the database functionis a regular or UDF function
So, may be a nice way to speed up database functions you don’t control For example: executing functions in dbms_* packages
Conclusions from these performance tests
UDF function calling another function • Whether the second function is regular or UDF has
almost no impact on performance in this case
Regular function calling another function • Whether the second function is regular or UDF has
almost no impact on performance in this case
(Pipelined) Table Function, PTF
A quick (lot less extensive) test for table function
- Just for:parameter = number return = Nested Table of two numbers
- Compare regular pipelined table function with UDF version
- Run both 11 times, ignore the first result
- Flush the shared pool after each (11 executions of a) test
- Tests were executed so the functions return 5 million rows
(Pipelined) Table Function, PTF
Results:
So, no difference at all
Comment by Bryn Llewellyn:
“Correct, and as expected because pipelined table functions are already, and always have been optimized for use in sql queries”
Test Runtime Std Dev 95% confidence Ratio
REGULAR PTF 2,939 0,043 0,027 100,000
UDF PTF 2,947 0,047 0,029 100,000
“People often say that there are no stupid questions.They are wrong. They actually do exist.But it takes a lot more time and energy to correct a stupid mistake than it takes to answer a stupid question, so please ask your stupid questions.”
a wise teacher who didn't just teach me physics