Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Thomas.

Asked: August 25, 2017 - 2:00 pm UTC

Last updated: August 31, 2017 - 7:49 am UTC

Version: 12.1.0.2

Viewed 1000+ times

You Asked

Dear AskTOM-Team,

It would be great if you can share your opinion on anydata-datatype.

Background to my question is, I'm using anydata-Type in conjunction with dbms_sql. To handle a dynamic-sql with their correct datatypes.
After a few tests I found out, that the anydata.access* / anydata.get* methods cause a significant time overhead.
I've seen Bug 17487865 but our environment is 12.1.0.2 on AIX 6.1 - v$version:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
"CORE 12.1.0.2.0 Production"
TNS for IBM/AIX RISC System/6000: Version 12.1.0.2.0 - Production
NLSRTL Version 12.1.0.2.0 - Production


and livesql is running 12.2.0.1.
So according to support.oracle this bug should be fixed in both versions.

I've provided some test-cases on livesql - they all use "index by varchar2(128)", which is close to our production-implementation.

It would be great if you can have a look at these, and either let me know if this is the time-overhead I've to live with when using anydata.
Or if this isn't the correct usage of anydata. Or if I've missed a note/bug in support.oracle.

Here are the links to my testcases:
.) Prerequisites
Help-Package to measure (cpu_)time - help.pkg:
https://livesql.oracle.com/apex/livesql/s/fgw9d652y2pduicuhfope1b90

Custom Object-Type for one testcase - my_datatype:
https://livesql.oracle.com/apex/livesql/s/fgxi5zeg51kmmkqj4o8le31eb

.) Test-Cases
The testcases are - hopefully - rather simple, they always fill an array with 1mio entries, and than access it again.
Anydata-index my varchar2(128) - any.vc2:
https://livesql.oracle.com/apex/livesql/s/fgxspb4ssakdm1nbl9leplhn5

My-custom-object-type - my.type.vc2:
https://livesql.oracle.com/apex/livesql/s/fgxi5zeg2uqh0gqoulo6vws8z

Record within pl/sql - my.vc2:
https://livesql.oracle.com/apex/livesql/s/fgxspb4sr43ij901j2khf3z41


Here are the times on livesql for each step (fill / access) for each test-case.
The column "d_step" shows the time in sec. needed for this step (dbms_utility.get_time)
Anydata:
 step      start   d_step      cpu    d_cpu  text
 ----    -------  -------  -------  -------  -------------------
   0.     0.0000   0.0000   0.0000   0.0000  BEGIN
   1.    10.2500  10.2500   8.8600   8.8600  fill anydata
   2.    19.7400   9.4900  18.2100   9.3500  loop GET anydata
   3.    30.6500  10.9100  29.0400  10.8300  loop ACCESS anydata
   4.    30.6500   0.0000  29.0400   0.0000  END

As you can see, it took ~9sec to access the 1mio entries with anydata.Get* and nearly 11sec with anydata.Access* methods.
In all my tests Get* is always slightly faster than Access*.

Custom-object-type:
 step      start   d_step      cpu    d_cpu  text
 ----    -------  -------  -------  -------  ------------
   0.     0.0000   0.0000   0.0000   0.0000  BEGIN
   1.     9.9700   9.9700   6.0500   6.0500  fill my type
   2.    11.5500   1.5800   7.6300   1.5800  loop my type
   3.    11.5500   0.0000   7.6300   0.0000  END

Only took 1.5 sec to loop over the a custom-object-type.

Record within pl/sql:
 step      start   d_step      cpu    d_cpu  text
 ----    -------  -------  -------  -------  -----------
   0.     0.0000   0.0000   0.0000   0.0000  BEGIN
   1.     9.2200   9.2200   5.2700   5.2700  fill mydata
   2.    10.0600   0.8400   6.1000   0.8300  loop mydata
   3.    10.0600   0.0000   6.1000   0.0000  END

And it only took .8sec to loop over a record/table.

The Custom-Object-Type test is rather rough, to be honest I didn't put too much effort into this test. I was just curious how it would compare to the other two.

I thought that the record would be the fastest method, but I didn't expect ~10sec for anydata.

Our AIX is almost 2 times slower than livesql - but the ration is the same.
For comparison here are the times (d_step) for the loop-steps only :
Anydata:
16.7200  loop GET anydata
19.1300  loop ACCESS anydata

Custom-object-type:
3.0500   loop my type

pl/sql-record:
1.5100   loop mydata


As mentioned above, I'd like to know if the usage of anydata would cause such a timing-overhead, or if this is the wrong usage of anydata at all.

Please take all the time you need to look into these testcases, and please let me know if there is any additional information I can provide.
No need to hurry, because - you know - nobody cares if a batch-job during the night runs for 10 minutes or 1 hour...
And in the end I'll probably rewrite everything to a pl/sql-record/table.

If you like, I've also done tests with "index by pls_integer" and "nested tables", but there is no significant timing difference, so I thought I spare these cases.

Looking forward to your answer, and thank you in advance not only for looking into my question, but for all your time and knowledge you've provided to the oracle-community over the years!

best regards,
Thomas

and Connor said...

I got similar results on my own 12.2 instance

SQL> exec any_test1
=== ANYDATA VARCHAR2 ===
step      start   d_step      cpu    d_cpu  text
----    -------  -------  -------  -------  ---------------------
0.     0.0000   0.0000   0.0000   0.0000  BEGIN
1.     6.6900   6.6900   4.3400   4.3400  fill anydata
2.    12.4000   5.7100  10.0600   5.7200  loop GET anydata
3.    19.1100   6.7100  16.7700   6.7100  loop ACCESS anydata
4.    19.1100   0.0000  16.7700   0.0000  END

PL/SQL procedure successfully completed.

SQL> exec any_test2
=== MY TYPE VARCHAR2 ===
step      start   d_step      cpu    d_cpu  text
----    -------  -------  -------  -------  ---------------------
0.     0.0000   0.0000   0.0000   0.0000  BEGIN
1.     9.8000   9.8000   3.2800   3.2800  fill my type
2.    10.9200   1.1200   4.4100   1.1300  loop my type
3.    10.9200   0.0000   4.4100   0.0000  END

PL/SQL procedure successfully completed.


To be honest that doesn't really surprise me. In order for ANYDATA to really support *any* data, then there's a tradeoff for that flexibility. You can get an idea of this by looking at the storage

SQL> create table t ( a int, x sys.anydata );

Table created.

SQL> insert into t values ( 1, sys.anyData.convertNumber(5) );

1 row created.

SQL> insert into t values ( 2, sys.anyData.convertDate(sysdate) );

1 row created.

SQL> insert into t values ( 3, sys.anyData.convertVarchar2('hello world') );

1 row created.

SQL> insert into t values ( 4, sys.anyData.convertVarchar2('hello world hello world hello world') );

1 row created.

SQL> select a, vsize(x) from t;

         A   VSIZE(X)
---------- ----------
         1         48
         2         53
         3         57
         4         81



So we've obviously got around 50 bytes of metadata overhead. ANYDATA has a tougher job because it is not just scalar datatypes we'll accept - we'll take object types, collections etc etc...

But I've passed your excellent test case onto some internal people for their thoughts as well. I'll update the answer with their comments as well in due course.

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thomas Stummer, August 29, 2017 - 7:45 am UTC

Dear Connor,

Thank you for your immediate response! I was afraid that the times didn't surprise you.
Sure anydata can handle - well - any type of data, hence the name i guess ;-)
But there must be a lot going on in either the Access/Get methods or in the internal storage/retrieving mechanism.

Anyhow, thank you for your time and effort, and for asking your internal people!
I'm looking forward to their response!

have a nice day,
Thomas

Connor McDonald
August 31, 2017 - 7:49 am UTC

From the internal team:

-------------
Anydata is a SQL object and every operation (set, get etc) involves a callout invocation from PLSQL engine to SQL engine. I would indeed expect a native packaged implementation to be better in terms of performance when dealing only with scalar types.

Advantages of Anydata as against PL/SQL packaged types include :-
- Ability to pass object around between SQL, PL/SQL, OCI, JDBC etc.
- Ability to persist as column in relational table.
- Ability to handle any ADTs and Collections.
-------------

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library