Query performance improvement using pipelined table function
Hi,
I have got two select queries one is like...
select * from table
another is using pielined table function
select *
from table(pipelined_function(cursor(select * from table)))
which query will return result set more faster????????
suggest methods for retrieving dataset more faster (using pipelined table function) than a normal select query.
rgds
somy
Compare the performance between these solutions:
create table big as select * from all_objects;
First test the performance of a normal select statement:
begin
for r in (select * from big) loop
null;
end loop;
end;
/Second a pipelined function:
create type rc_vars as object
(OWNER VARCHAR2(30)
,OBJECT_NAME VARCHAR2(30));
create or replace type rc_vars_table as table of rc_vars ;
create or replace
function rc_get_vars
return rc_vars_table
pipelined
as
cursor c_aobj
is
select owner, object_name
from big;
l_aobj c_aobj%rowtype;
begin
for r_aobj in c_aobj loop
pipe row(rc_vars(r_aobj.owner,r_aobj.object_name));
end loop;
return;
end;
/Test the performance of the pipelined function:
begin
for r in (select * from table(rc_get_vars)) loop
null;
end loop;
end;
/On my system the simple select-statement is 20 times faster.
Correction: It is 10 times faster, not 20.
Message was edited by:
wateenmooiedag
Similar Messages
-
Using Pipeline Table functions with other tables
I am on DB 11.2.0.2 and have sparingly used pipelined table functions but am considering it for a project that has some fairly big (lots of rows) sized tables. In my tests, selecting from just the pipelined table perform pretty well (whether it is directly from the pipleined table or the view I created on top of it). Where I start to see some degregation when I try to join the pipelined tabe view to other tables and add where conditions.
ie:
SELECT A.empno, A.empname, A.job, B.sal
FROM EMP_VIEW A, EMP B
WHERE A.empno = B.empno AND
B.mgr = '7839'
I have seen some articles and blogs that mention this as a cardinality issue, and offer some undocumented methods to try and combat.
Can someone please give me some advice or tips on this. Thanks!
I have created a simple example using the emp table below to help illustrate what I am doing.
DROP TYPE EMP_TYPE;
DROP TYPE EMP_SEQ;
CREATE OR REPLACE TYPE EMP_SEQ AS OBJECT
( EMPNO NUMBER(10),
ENAME VARCHAR2(100),
JOB VARCHAR2(100));
CREATE OR REPLACE TYPE EMP_TYPE AS TABLE OF EMP_SEQ;
CREATE OR REPLACE FUNCTION get_emp return EMP_TYPE PIPELINED AS
BEGIN
FOR cur IN (SELECT
empno,
ename,
job
FROM emp
LOOP
PIPE ROW(EMP_SEQ(cur.empno,
cur.ename,
cur.job));
END LOOP;
RETURN;
END get_emp;
create OR REPLACE view EMP_VIEW as select * from table(get_emp());
SELECT A.empno, A.empname, A.job, B.sal
FROM EMP_VIEW A, EMP B
WHERE A.empno = B.empno AND
B.mgr = '7839'I am on DB 11.2.0.2 and have sparingly used pipelined table functions but am considering it for a project that has some fairly big (lots of rows) sized tables
Which begs the question: WHY? What PROBLEM are you trying to solve and what makes you think using pipelined table functions is the best way to solve that problem?
The lack of information about cardinality is the likely root of the degradation you noticed as already mentioned.
But that should be a red flag about pipelined functions in general. PIPELINED functions hide virtually ALL KNOWLEDGE about the result set that is produced; cardinality is just the tip of the iceberg. Those functions pretty much say 'here is a result set' without ANY information about the number of rows (cardinality), distinct values for any columns, nullability of any columns, constraints that might apply to any columns (foreign key, primary key) and so on.
If you are going to hide all of that information from Oracle that would normally be used to help optimize queries and select the appropriate execution plan you need to have a VERY good reason.
The use of PIPELINED functions should be reserved for those use cases where ordinary SQL and PL/SQL cannot get the job done. That is they are a 'special case' solution.
The classic use case for those functions is for the transform stage of ETL where multiple pipelined functions are chained together: one function feeds its rows to the next function which feeds its rows to another and so on. Each of those 'chained' functions is roughly analogous to a full table scan of the data that often does not need to be joined to other data except perhaps low volumn lookup tables where the data may even be cached.
I suggest that any exploratory or prototyping work you do use standard relational tables until such point as you run into a problem whose solution might require PIPELINED functions to solve. -
Performance issues with pipelined table functions
I am testing pipelined table functions to be able to re-use the <font face="courier">base_query</font> function. Contrary to my understanding, the <font face="courier">with_pipeline</font> procedure runs 6 time slower than the legacy <font face="courier">no_pipeline</font> procedure. Am I missing something? The <font face="courier">processor</font> function is from [url http://www.oracle-developer.net/display.php?id=429]improving performance with pipelined table functions .
Edit: The underlying query returns 500,000 rows in about 3 minutes. So there are are no performance issues with the query itself.
Many thanks in advance.
CREATE OR REPLACE PACKAGE pipeline_example
IS
TYPE resultset_typ IS REF CURSOR;
TYPE row_typ IS RECORD (colC VARCHAR2(200), colD VARCHAR2(200), colE VARCHAR2(200));
TYPE table_typ IS TABLE OF row_typ;
FUNCTION base_query (argA IN VARCHAR2, argB IN VARCHAR2)
RETURN resultset_typ;
c_default_limit CONSTANT PLS_INTEGER := 100;
FUNCTION processor (
p_source_data IN resultset_typ,
p_limit_size IN PLS_INTEGER DEFAULT c_default_limit)
RETURN table_typ
PIPELINED
PARALLEL_ENABLE(PARTITION p_source_data BY ANY);
PROCEDURE with_pipeline (argA IN VARCHAR2,
argB IN VARCHAR2,
o_resultset OUT resultset_typ);
PROCEDURE no_pipeline (argA IN VARCHAR2,
argB IN VARCHAR2,
o_resultset OUT resultset_typ);
END pipeline_example;
CREATE OR REPLACE PACKAGE BODY pipeline_example
IS
FUNCTION base_query (argA IN VARCHAR2, argB IN VARCHAR2)
RETURN resultset_typ
IS
o_resultset resultset_typ;
BEGIN
OPEN o_resultset FOR
SELECT colC, colD, colE
FROM some_table
WHERE colA = ArgA AND colB = argB;
RETURN o_resultset;
END base_query;
FUNCTION processor (
p_source_data IN resultset_typ,
p_limit_size IN PLS_INTEGER DEFAULT c_default_limit)
RETURN table_typ
PIPELINED
PARALLEL_ENABLE(PARTITION p_source_data BY ANY)
IS
aa_source_data table_typ;-- := table_typ ();
BEGIN
LOOP
FETCH p_source_data
BULK COLLECT INTO aa_source_data
LIMIT p_limit_size;
EXIT WHEN aa_source_data.COUNT = 0;
/* Process the batch of (p_limit_size) records... */
FOR i IN 1 .. aa_source_data.COUNT
LOOP
PIPE ROW (aa_source_data (i));
END LOOP;
END LOOP;
CLOSE p_source_data;
RETURN;
END processor;
PROCEDURE with_pipeline (argA IN VARCHAR2,
argB IN VARCHAR2,
o_resultset OUT resultset_typ)
IS
BEGIN
OPEN o_resultset FOR
SELECT /*+ PARALLEL(t, 5) */ colC,
SUM (CASE WHEN colD > colE AND colE != '0' THEN colD / ColE END)de,
SUM (CASE WHEN colE > colD AND colD != '0' THEN colE / ColD END)ed,
SUM (CASE WHEN colD = colE AND colD != '0' THEN '1' END) de_one,
SUM (CASE WHEN colD = '0' OR colE = '0' THEN '0' END) de_zero
FROM TABLE (processor (base_query (argA, argB),100)) t
GROUP BY colC
ORDER BY colC
END with_pipeline;
PROCEDURE no_pipeline (argA IN VARCHAR2,
argB IN VARCHAR2,
o_resultset OUT resultset_typ)
IS
BEGIN
OPEN o_resultset FOR
SELECT colC,
SUM (CASE WHEN colD > colE AND colE != '0' THEN colD / ColE END)de,
SUM (CASE WHEN colE > colD AND colD != '0' THEN colE / ColD END)ed,
SUM (CASE WHEN colD = colE AND colD != '0' THEN 1 END) de_one,
SUM (CASE WHEN colD = '0' OR colE = '0' THEN '0' END) de_zero
FROM (SELECT colC, colD, colE
FROM some_table
WHERE colA = ArgA AND colB = argB)
GROUP BY colC
ORDER BY colC;
END no_pipeline;
END pipeline_example;
ALTER PACKAGE pipeline_example COMPILE;Edited by: Earthlink on Nov 14, 2010 9:47 AM
Edited by: Earthlink on Nov 14, 2010 11:31 AM
Edited by: Earthlink on Nov 14, 2010 11:32 AM
Edited by: Earthlink on Nov 20, 2010 12:04 PM
Edited by: Earthlink on Nov 20, 2010 12:54 PMEarthlink wrote:
Contrary to my understanding, the <font face="courier">with_pipeline</font> procedure runs 6 time slower than the legacy <font face="courier">no_pipeline</font> procedure. Am I missing something? Well, we're missing a lot here.
Like:
- a database version
- how did you test
- what data do you have, how is it distributed, indexed
and so on.
If you want to find out what's going on then use a TRACE with wait events.
All nessecary steps are explained in these threads:
HOW TO: Post a SQL statement tuning request - template posting
http://oracle-randolf.blogspot.com/2009/02/basic-sql-statement-performance.html
Another nice one is RUNSTATS:
http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551378329289980701 -
Interactive report on view based on pipelined table function.
Hi,
I want to build an Interactive Report on a view.
The view definition contains a select on a pipelined table function. I use context functionality to pass paramaters to the pipelined table function.
A plain select * from #my_view# in SqlPlus results in 121 different rows.
However, If I base my Interactive report on this view, I get 15 repeated rows (all the same).
Is it possible to use pipelined table functionality on an Interactive report? I can't seem to get it working.
If I use the following approach (http://rakeshjsr.blogspot.nl/2010/10/oracle-apex-interactive-report-based-on.html) I do get results, but I can't use this solution for a reason that's not relevant.Hello,
Is it possible to use pipelined table functionality on an Interactive report? I can't seem to get it working. I have used it in one instance and it works fine. However I was passing the values to pipe-lined function directly.
IR Query..
SELECT * FROM TABLE(fn_pipeline(:P1_ITEM_NAME))Call pipe-lined function from IR query directly (instead of using view)
Try sending values to Pipe-lined function directly. In-case if the problem is with setting and getting values from the context?
Regards,
Hari -
Pipeline Table Function returning a fraction of data
My current project involves migrating an Oracle database to a new structure based on the new client application requirements. I would like to use pipelined table functions as it seems as though that would provide the best performance.
The first table has about 65 fields, about 75% of which require some type of recoding for the new app. I have written a function for each transformation and have all of these functions stored in a package. If I do:
create new_table as select (
pkg_name.function1(old_field1),
pkg_name.function2(old_field2),
pkg_name.function3(old_field3),
it runs with out any errors but takes about 3 1/2 hours. There are a little more than 10 million rows in the table.
I wrote a function that is passed the old table as a cursor, runs all the functions for the transformations and then pipes the new row back to the insert statement that called the function. It is incredibly fast but only returns .025% of the data (about 50 rows out of my sample table of 200,000). It does not throw any errors.
So I am trying to determine what is going on. Perhaps one of my functions has a bug. If there was would cause the row to be kicked out? There are 40 or so functions so tracking this down has been a bit of a bear.
Any advice as to how I might resolve this would be much appreciated.
Thanks
Dan. I would like to use pipelined table functions as it seems as though that would provide the best performanceUh huh...
it runs with out any errors but takes about 3 1/2 hours. There are a little more than 10 million rows in the table.Not the first time a lovely theory has been killed by an ugly fact. Did you do any bench marks to see whether the pipelined functions did offer performance benefits over doing it some other way?
From the context of your comments I think you are trying to a populate a new table from a single old table. Is this the case? If so I would have thought a straightforward CTAS with normal functions would be more appropriate: pipelined functions are really meant for situations in which one input produced more than one output. Anyway, ifr we are to help you I think you need to give us more details about how this process works and post a sample transformation function.
There are 40 or so functions so tracking this down has been a bit of a bear.The teaching is: we should code one function and get that working before moving on to the next one. Which might not seem like a helpful thing to say, but the best lesson is often "I'll do it differently next time".
Cheers, APC -
Distributed queries+pipelined table function
HI friends,
can i get better performance for distributed queries if i use pipelined table function.I have got my data distribued across three different databases.
thanx
somyYou will need to grant EXECUTE access on the pipelined table function to whatever users want it. When other users call this function, they may need to prefix the schema owner (i.e. <<owner>>.getValue('001') ) unless you've set up the appropriate synonym.
What version of SQL*Plus do you have on the NT machine?
Justin
Distributed Database Consulting, Inc.
http://www.ddbcinc.com/askDDBC -
10g: delay for collecting results from parallel pipelined table functions
When parallel pipelined table functions are properly started and generate output record, there is a delay for the consuming main thread to gather these records.
This delay is huge compared with the run-time of the worker threads.
For my application it goes like this:
main thread timing efforts to start worker and collect their results:
[10:50:33-*10:50:49*]:JOMA: create (master): 015.93 sec (#66356 records, #4165/sec)
worker threads:
[10:50:34-*10:50:39*]:JOMA: create (slave) : 005.24 sec (#2449 EDRs, #467/sec, #0 errored / #6430 EBTMs, #1227/sec, #0 errored) - bulk #1 / sid #816
[10:50:34-*10:50:39*]:JOMA: create (slave) : 005.56 sec (#2543 EDRs, #457/sec, #0 errored / #6792 EBTMs, #1221/sec, #0 errored) - bulk #1 / sid #718
[10:50:34-*10:50:39*]:JOMA: create (slave) : 005.69 sec (#2610 EDRs, #459/sec, #0 errored / #6950 EBTMs, #1221/sec, #0 errored) - bulk #1 / sid #614
[10:50:34-*10:50:39*]:JOMA: create (slave) : 005.55 sec (#2548 EDRs, #459/sec, #0 errored / #6744 EBTMs, #1216/sec, #0 errored) - bulk #1 / sid #590
[10:50:34-*10:50:39*]:JOMA: create (slave) : 005.33 sec (#2461 EDRs, #462/sec, #0 errored / #6504 EBTMs, #1220/sec, #0 errored) - bulk #1 / sid #508
You can see, the worker threads are all started at the same time and terminating at the same time: 10:50:34-10:50:*39*.
But the main thread just invoking them and saving their results into a collection has finished at 10:50:*49*.
Why does it need #10 sec more just to save the data?
Here's a sample sqlplus script to demonstrate this:
--------------------------- snip -------------------------------------------------------
set serveroutput on;
drop table perf_data;
drop table test_table;
drop table tmp_test_table;
drop type ton_t;
drop type test_list;
drop type test_obj;
create table perf_data
sid number,
t1 timestamp with time zone,
t2 timestamp with time zone,
client varchar2(256)
create table test_table
a number(19,0),
b timestamp with time zone,
c varchar2(256)
create global temporary table tmp_test_table
a number(19,0),
b timestamp with time zone,
c varchar2(256)
create or replace type test_obj as object(
a number(19,0),
b timestamp with time zone,
c varchar2(256)
create or replace type test_list as table of test_obj;
create or replace type ton_t as table of number;
create or replace package test_pkg
as
type test_rec is record (
a number(19,0),
b timestamp with time zone,
c varchar2(256)
type test_tab is table of test_rec;
type test_cur is ref cursor return test_rec;
function TZDeltaToMilliseconds(
t1 in timestamp with time zone,
t2 in timestamp with time zone)
return pls_integer;
function TF(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by hash(a));
end;
create or replace package body test_pkg
as
* Calculate timestamp with timezone difference
* in milliseconds
function TZDeltaToMilliseconds(
t1 in timestamp with time zone,
t2 in timestamp with time zone)
return pls_integer
is
begin
return (extract(hour from t2) - extract(hour from t1)) * 3600 * 1000
+ (extract(minute from t2) - extract(minute from t1)) * 60 * 1000
+ (extract(second from t2) - extract(second from t1)) * 1000;
end TZDeltaToMilliseconds;
function TF(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by hash(a))
is
pragma autonomous_transaction;
sid number;
counter number(19,0) := 0;
myrec test_rec;
mytab test_tab;
mytab2 test_list := test_list();
t1 timestamp with time zone;
t2 timestamp with time zone;
begin
t1 := systimestamp;
select userenv('SID') into sid from dual;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
loop
fetch mycur into myRec;
exit when mycur%NOTFOUND;
mytab2.extend;
mytab2(mytab2.last) := test_obj(myRec.a, myRec.b, myRec.c);
end loop;
for i in mytab2.first..mytab2.last loop
-- attention: saves own SID in test_obj.a for indication to caller
-- how many sids have been involved
pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c));
pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c)); -- duplicate
pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c)); -- duplicate once again
counter := counter + 1;
end loop;
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
commit;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
end;
end;
declare
myList test_list := test_list();
myList2 test_list := test_list();
sids ton_t := ton_t();
sid number;
t1 timestamp with time zone;
t2 timestamp with time zone;
procedure LogPerfTable
is
type ton is table of number;
type tot is table of timestamp with time zone;
type clients_t is table of varchar2(256);
sids ton;
t1s tot;
t2s tot;
clients clients_t;
deltaTime integer;
btsPerSecond number(19,0);
edrsPerSecond number(19,0);
begin
select sid, t1, t2, client bulk collect into sids, t1s, t2s, clients from perf_data order by client;
if clients.count > 0 then
for i in clients.FIRST .. clients.LAST loop
deltaTime := test_pkg.TZDeltaToMilliseconds(t1s(i), t2s(i));
if deltaTime = 0 then deltaTime := 1; end if;
dbms_output.put_line(
'[' || to_char(t1s(i), 'hh:mi:ss') ||
'-' || to_char(t2s(i), 'hh:mi:ss') ||
']:' ||
' client ' || clients(i) || ' / sid #' || sids(i)
end loop;
end if;
end LogPerfTable;
begin
select userenv('SID') into sid from dual;
for i in 1..200000 loop
myList.extend; myList(myList.last) := test_obj(i, sysdate, to_char(i+2));
end loop;
-- save into the real table
insert into test_table select * from table(cast (myList as test_list));
-- save into the tmp table
insert into tmp_test_table select * from table(cast (myList as test_list));
dbms_output.put_line(chr(10) || '(1) copy ''mylist'' to ''mylist2'' by streaming via table function...');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from table(cast (myList as test_list)) tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(2) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(3) copy physical ''test_table'' to ''mylist2'' by streaming via table function:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
end;
--------------------------- snap -------------------------------------------------------
best regards,
FrankHello
I think the delay you are seeing is down to choosing the partitioning method as HASH. When you specify anything other than ANY, an additional buffer sort is included in the execution plan...
create or replace package test_pkg
as
type test_rec is record (
a number(19,0),
b timestamp with time zone,
c varchar2(256)
type test_tab is table of test_rec;
type test_cur is ref cursor return test_rec;
function TZDeltaToMilliseconds(
t1 in timestamp with time zone,
t2 in timestamp with time zone)
return pls_integer;
function TF(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by hash(a));
function TF_Any(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by ANY);
end;
create or replace package body test_pkg
as
* Calculate timestamp with timezone difference
* in milliseconds
function TZDeltaToMilliseconds(
t1 in timestamp with time zone,
t2 in timestamp with time zone)
return pls_integer
is
begin
return (extract(hour from t2) - extract(hour from t1)) * 3600 * 1000
+ (extract(minute from t2) - extract(minute from t1)) * 60 * 1000
+ (extract(second from t2) - extract(second from t1)) * 1000;
end TZDeltaToMilliseconds;
function TF(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by hash(a))
is
pragma autonomous_transaction;
sid number;
counter number(19,0) := 0;
myrec test_rec;
t1 timestamp with time zone;
t2 timestamp with time zone;
begin
t1 := systimestamp;
select userenv('SID') into sid from dual;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
loop
fetch mycur into myRec;
exit when mycur%NOTFOUND;
-- attention: saves own SID in test_obj.a for indication to caller
-- how many sids have been involved
pipe row(test_obj(sid, myRec.b, myRec.c));
pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate
pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate once again
counter := counter + 1;
end loop;
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
commit;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
end;
function TF_any(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by ANY)
is
pragma autonomous_transaction;
sid number;
counter number(19,0) := 0;
myrec test_rec;
t1 timestamp with time zone;
t2 timestamp with time zone;
begin
t1 := systimestamp;
select userenv('SID') into sid from dual;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
loop
fetch mycur into myRec;
exit when mycur%NOTFOUND;
-- attention: saves own SID in test_obj.a for indication to caller
-- how many sids have been involved
pipe row(test_obj(sid, myRec.b, myRec.c));
pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate
pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate once again
counter := counter + 1;
end loop;
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
commit;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
end;
end;
explain plan for
select /*+ first_rows */ test_obj(a, b, c)
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
select * from table(dbms_xplan.display);
Plan hash value: 1037943675
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
| 0 | SELECT STATEMENT | | 8168 | 3972K| 20 (0)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 | 8168 | 3972K| 20 (0)| 00:00:01 | Q1,01 | P->S | QC (RAND) |
| 3 | BUFFER SORT | | 8168 | 3972K| | | Q1,01 | PCWP | |
| 4 | VIEW | | 8168 | 3972K| 20 (0)| 00:00:01 | Q1,01 | PCWP | |
| 5 | COLLECTION ITERATOR PICKLER FETCH| TF | | | | | Q1,01 | PCWP | |
| 6 | PX RECEIVE | | 931K| 140M| 136 (2)| 00:00:02 | Q1,01 | PCWP | |
| 7 | PX SEND HASH | :TQ10000 | 931K| 140M| 136 (2)| 00:00:02 | Q1,00 | P->P | HASH |
| 8 | PX BLOCK ITERATOR | | 931K| 140M| 136 (2)| 00:00:02 | Q1,00 | PCWC | |
| 9 | TABLE ACCESS FULL | TEST_TABLE | 931K| 140M| 136 (2)| 00:00:02 | Q1,00 | PCWP | |
Note
- dynamic sampling used for this statement
explain plan for
select /*+ first_rows */ test_obj(a, b, c)
from table(test_pkg.TF_Any(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
select * from table(dbms_xplan.display);
Plan hash value: 4097140875
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
| 0 | SELECT STATEMENT | | 8168 | 3972K| 20 (0)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10000 | 8168 | 3972K| 20 (0)| 00:00:01 | Q1,00 | P->S | QC (RAND) |
| 3 | VIEW | | 8168 | 3972K| 20 (0)| 00:00:01 | Q1,00 | PCWP | |
| 4 | COLLECTION ITERATOR PICKLER FETCH| TF_ANY | | | | | Q1,00 | PCWP | |
| 5 | PX BLOCK ITERATOR | | 931K| 140M| 136 (2)| 00:00:02 | Q1,00 | PCWC | |
| 6 | TABLE ACCESS FULL | TEST_TABLE | 931K| 140M| 136 (2)| 00:00:02 | Q1,00 | PCWP | |
Note
- dynamic sampling used for this statementI posted about it here a few years ago and I more recently posted a question on Asktom. Unfortunately Tom was not able to find a technical reason for it to be there so I'm still a little in the dark as to why it is needed. The original question I posted is here:
Pipelined function partition by hash has extra sort#
I ran your tests with HASH vs ANY and the results are in line with the observations above....
declare
myList test_list := test_list();
myList2 test_list := test_list();
sids ton_t := ton_t();
sid number;
t1 timestamp with time zone;
t2 timestamp with time zone;
procedure LogPerfTable
is
type ton is table of number;
type tot is table of timestamp with time zone;
type clients_t is table of varchar2(256);
sids ton;
t1s tot;
t2s tot;
clients clients_t;
deltaTime integer;
btsPerSecond number(19,0);
edrsPerSecond number(19,0);
begin
select sid, t1, t2, client bulk collect into sids, t1s, t2s, clients from perf_data order by client;
if clients.count > 0 then
for i in clients.FIRST .. clients.LAST loop
deltaTime := test_pkg.TZDeltaToMilliseconds(t1s(i), t2s(i));
if deltaTime = 0 then deltaTime := 1; end if;
dbms_output.put_line(
'[' || to_char(t1s(i), 'hh:mi:ss') ||
'-' || to_char(t2s(i), 'hh:mi:ss') ||
']:' ||
' client ' || clients(i) || ' / sid #' || sids(i)
end loop;
end if;
end LogPerfTable;
begin
select userenv('SID') into sid from dual;
for i in 1..200000 loop
myList.extend; myList(myList.last) := test_obj(i, sysdate, to_char(i+2));
end loop;
-- save into the real table
insert into test_table select * from table(cast (myList as test_list));
-- save into the tmp table
insert into tmp_test_table select * from table(cast (myList as test_list));
dbms_output.put_line(chr(10) || '(1) copy ''mylist'' to ''mylist2'' by streaming via table function...');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from table(cast (myList as test_list)) tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(2) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(3) copy physical ''test_table'' to ''mylist2'' by streaming via table function:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(4) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function ANY:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF_any(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(5) copy physical ''test_table'' to ''mylist2'' by streaming via table function using ANY:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF_any(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
end;
(1) copy 'mylist' to 'mylist2' by streaming via table function...
test_pkg.TF( sid => '918' ): enter
test_pkg.TF( sid => '918' ): exit, piped #200000 records
[01:40:19-01:40:29]: client master / sid #918
[01:40:19-01:40:29]: client slave / sid #918
... saved #600000 records
(2) copy temporary 'tmp_test_table' to 'mylist2' by streaming via table function:
[01:40:31-01:40:36]: client master / sid #918
[01:40:31-01:40:32]: client slave / sid #659
[01:40:31-01:40:32]: client slave / sid #880
[01:40:31-01:40:32]: client slave / sid #1045
[01:40:31-01:40:32]: client slave / sid #963
[01:40:31-01:40:32]: client slave / sid #712
... saved #600000 records
(3) copy physical 'test_table' to 'mylist2' by streaming via table function:
[01:40:37-01:41:05]: client master / sid #918
[01:40:37-01:40:42]: client slave / sid #738
[01:40:37-01:40:42]: client slave / sid #568
[01:40:37-01:40:42]: client slave / sid #618
[01:40:37-01:40:42]: client slave / sid #659
[01:40:37-01:40:42]: client slave / sid #963
... saved #3000000 records
(4) copy temporary 'tmp_test_table' to 'mylist2' by streaming via table function ANY:
[01:41:12-01:41:16]: client master / sid #918
[01:41:12-01:41:16]: client slave / sid #712
[01:41:12-01:41:16]: client slave / sid #1045
[01:41:12-01:41:16]: client slave / sid #681
[01:41:12-01:41:16]: client slave / sid #754
[01:41:12-01:41:16]: client slave / sid #880
... saved #600000 records
(5) copy physical 'test_table' to 'mylist2' by streaming via table function using ANY:
[01:41:18-01:41:38]: client master / sid #918
[01:41:18-01:41:38]: client slave / sid #681
[01:41:18-01:41:38]: client slave / sid #712
[01:41:18-01:41:38]: client slave / sid #754
[01:41:18-01:41:37]: client slave / sid #880
[01:41:18-01:41:38]: client slave / sid #1045
... saved #3000000 recordsHTH
David -
Parallel pipelined table function, autonomous_transaction to global tmp tab
Hi,
i try to speed up my parallel pipelined table function and switch from pl/sql collection to global temporary table inside.
This requires to use PRAGMA AUTONOMOUS_TRANSACTION (and commit), because inserting into global temporary table (DML)
within select - for invoking the table function - is not allowed without.
As a consequence of commit it next requires to have on commit preserve rows for the global temporary table.
Now:
Inserts into the global temporary table are done - indicated by sql%rowcount.
But a select afterwards doesn't show any record anymore.
Here is a program to demonstrate it:
set serveroutput on;
drop type TestTableOfNumber_t;
create or replace type TestTableOfNumber_t is table of number;
drop type TestStatusList;
drop type TestStatusObj;
create or replace type TestStatusObj as object(
sid number,
ctr1 number,
ctr2 number,
ctr3 number
create or replace type TestStatusList is table of TestStatusObj;
drop table TestTmpTable;
create global temporary table TestTmpTable (
value number
) on commit preserve rows;
create or replace package test_pkg
as
type TestStatusRec is record (
sid number,
ctr1 number,
ctr2 number,
ctr3 number
type TestStatusTab is table of TestStatusRec;
function FillTmpTable(id in varchar2)
return TestStatusRec;
FUNCTION ptf (p_cursor IN sys_refcursor)
RETURN TestStatusList PIPELINED
PARALLEL_ENABLE(PARTITION p_cursor BY any);
end;
create or replace package body test_pkg
as
function FillTmpTable(id in varchar2)
return TestStatusRec
is
PRAGMA AUTONOMOUS_TRANSACTION;
result TestStatusRec;
sid number;
type ton is table of number;
tids TestTableOfNumber_t := TestTableOfNumber_t();
records number := 0;
begin
select userenv('SID') into sid from dual;
result.sid := sid;
delete from TestTmpTable;
for i in 1..100 loop
tids.extend;
tids(tids.last) := i;
end loop;
forall i in 1..tids.count
insert into TestTmpTable (value) values (tids(i));
-- get number of records inserted
records := sql%rowcount;
result.ctr1 := records;
-- retrieve again before commit
select count(*) into records from TestTmpTable;
result.ctr2 := records;
commit;
-- retrieve again after commit
select count(*) into records from TestTmpTable;
result.ctr3 := records;
return result;
end;
FUNCTION ptf (p_cursor IN sys_refcursor)
RETURN TestStatusList PIPELINED
PARALLEL_ENABLE(PARTITION p_cursor BY any)
IS
rec test_pkg.TestStatusRec;
value number;
sid number;
ctr integer := 0;
BEGIN
select userenv('SID') into sid from dual;
rec := FillTmpTable('IN PTF');
LOOP
FETCH p_cursor into value;
EXIT WHEN p_cursor%NOTFOUND;
ctr := ctr + 1;
END LOOP;
-- as a result i am only interested in the results of FillTmpTable():
PIPE ROW (TestStatusObj(rec.sid, rec.ctr1, rec.ctr2, rec.ctr3));
RETURN;
END;
end;
declare
tons TestTableOfNumber_t;
counts TestTableOfNumber_t;
status test_pkg.TestStatusRec;
statusList test_pkg.TestStatusTab;
begin
status := test_pkg.FillTmpTable('MAIN');
dbms_output.put_line('main thread:'
|| ' sid #' || status.sid
|| ' / #' || status.ctr1 || ' inserted '
|| ' / #' || status.ctr2 || ' before commit'
|| ' / #' || status.ctr3 || ' after commit');
select value bulk collect into tons from TestTmpTable;
select * bulk collect into statusList from TABLE(test_pkg.ptf(CURSOR(select /*+ parallel(tab,2) */ value from TestTmpTable tab)));
for i in 1..StatusList.count loop
dbms_output.put_line('worker thread #' || i || ':'
|| ' sid #' || statusList(i).sid
|| ' / #' || statusList(i).ctr1 || ' inserted '
|| ' / #' || statusList(i).ctr2 || ' before commit'
|| ' / #' || statusList(i).ctr3 || ' after commit');
end loop;
end;
/The output is:
main thread: sid #881 / #100 inserted / #100 before commit / #100 after commit
worker thread #1: sid #421 / #100 inserted / #0 before commit / #0 after commit
worker thread #2: sid #321 / #100 inserted / #0 before commit / #0 after commitThe 1st line is for the main thread invoking FillTmpTable().
The next #2 lines are for the worker threads of the parallel pipelined table function for invoking the same FillTmpTable().
For the main thread everything is as expected.
But for the worker threads the logs for before commit and after commit both give #0 for the number of available records in the global temporary table.
However all indicate #100 for the SQL insert
regards,
Frank
Edited by: user8704911 on Jul 7, 2011 10:13 AM
Edited by: user8704911 on Jul 7, 2011 10:20 AM
Edited by: user8704911 on Jul 7, 2011 10:27 AMSQL> select * from v$version;
BANNER
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
CORE 11.1.0.7.0 Production
TNS for Linux: Version 11.1.0.7.0 - Production
NLSRTL Version 11.1.0.7.0 - Production
SQL> set serveroutput on;
SQL> drop type TestTableOfNumber;
drop type TestTableOfNumber
ERROR at line 1:
ORA-04043: object TESTTABLEOFNUMBER does not exist
SQL> /
drop type TestTableOfNumber
ERROR at line 1:
ORA-04043: object TESTTABLEOFNUMBER does not exist
SQL>
SQL> create or replace type TestTableOfNumber_t is table of number;
2 /
Type created.
SQL>
SQL> drop type TestStatusObj;
drop type TestStatusObj
ERROR at line 1:
ORA-04043: object TESTSTATUSOBJ does not exist
SQL> /
drop type TestStatusObj
ERROR at line 1:
ORA-04043: object TESTSTATUSOBJ does not exist
SQL>
SQL> create or replace type TestStatusObj as object(
2 sid number,
3 ctr1 number,
4 ctr2 number,
5 ctr3 number
6 );
7 /
Type created.
SQL>
SQL> drop type TestStatusList;
drop type TestStatusList
ERROR at line 1:
ORA-04043: object TESTSTATUSLIST does not exist
SQL> /
drop type TestStatusList
ERROR at line 1:
ORA-04043: object TESTSTATUSLIST does not exist
SQL>
SQL> create or replace type TestStatusList is table of TestStatusObj;
2 /
Type created.
SQL>
SQL> drop table TestTmpTable;
drop table TestTmpTable
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> /
drop table TestTmpTable
ERROR at line 1:
ORA-00942: table or view does not exist
SQL>
SQL> create global temporary table TestTmpTable (
2 value number
3 ) on commit preserve rows;
Table created.
SQL> /
create global temporary table TestTmpTable (
ERROR at line 1:
ORA-00955: name is already used by an existing object
SQL>
SQL> create or replace package test_pkg
2 as
3
4 type TestStatusRec is record (
5 sid number,
6 ctr1 number,
7 ctr2 number,
8 ctr3 number
9 );
10
11 type TestStatusTab is table of TestStatusRec;
12
13 function FillTmpTable(id in varchar2)
14 return TestStatusRec;
15
16 FUNCTION ptf (p_cursor IN sys_refcursor)
17 RETURN TestStatusList PIPELINED
18 PARALLEL_ENABLE(PARTITION p_cursor BY any);
19
20 end;
21 /
Package created.
SQL>
SQL> create or replace package body test_pkg
2 as
3
4 function FillTmpTable(id in varchar2)
5 return TestStatusRec
6 is
7 PRAGMA AUTONOMOUS_TRANSACTION;
8
9 result TestStatusRec;
10
11 sid number;
12
13 type ton is table of number;
14 tids TestTableOfNumber_t := TestTableOfNumber_t();
15
16 records number := 0;
17 begin
18 select userenv('SID') into sid from dual;
19 result.sid := sid;
20
21 delete from TestTmpTable;
22
23 for i in 1..100 loop
24 tids.extend;
25 tids(tids.last) := i;
26 end loop;
27
28 forall i in 1..tids.count
29 insert into TestTmpTable (value) values (tids(i));
30
31 -- get number of records inserted
32 records := sql%rowcount;
33 result.ctr1 := records;
34
35 -- retrieve again before commit
36 select count(*) into records from TestTmpTable;
37 result.ctr2 := records;
38
39 commit;
40
41 -- retrieve again after commit
42 select count(*) into records from TestTmpTable;
43 result.ctr3 := records;
44
45 return result;
46 end;
47
48 FUNCTION ptf (p_cursor IN sys_refcursor)
49 RETURN TestStatusList PIPELINED
50 PARALLEL_ENABLE(PARTITION p_cursor BY any)
51 IS
52 rec test_pkg.TestStatusRec;
53 value number;
54 sid number;
55 ctr integer := 0;
56 BEGIN
57 select userenv('SID') into sid from dual;
58 rec := FillTmpTable('IN PTF');
59 LOOP
60 FETCH p_cursor into value;
61 EXIT WHEN p_cursor%NOTFOUND;
62 ctr := ctr + 1;
63 END LOOP;
64
65 -- as a result i am only interested in the results of FillTmpTable():
66 PIPE ROW (TestStatusObj(rec.sid, rec.ctr1, rec.ctr2, rec.ctr3));
67
68 RETURN;
69 END;
70 end;
71 /
Package body created.
SQL>
SQL> declare
2 tons TestTableOfNumber_t;
3 counts TestTableOfNumber_t;
4 status test_pkg.TestStatusRec;
5 statusList test_pkg.TestStatusTab;
6 begin
7 status := test_pkg.FillTmpTable('MAIN');
8 dbms_output.put_line('main thread:'
9 || ' sid #' || status.sid
10 || ' / #' || status.ctr1 || ' inserted '
11 || ' / #' || status.ctr2 || ' before commit'
12 || ' / #' || status.ctr3 || ' after commit');
13
14 select value bulk collect into tons from TestTmpTable;
15
16 select * bulk collect into statusList from TABLE(test_pkg.ptf(CURSOR(select /*+ parallel(tab,2
) */ value from TestTmpTable tab)));
17
18 for i in 1..StatusList.count loop
19 dbms_output.put_line('worker thread #' || i || ':'
20 || ' sid #' || statusList(i).sid
21 || ' / #' || statusList(i).ctr1 || ' inserted '
22 || ' / #' || statusList(i).ctr2 || ' before commit'
23 || ' / #' || statusList(i).ctr3 || ' after commit');
24 end loop;
25
26 end;
27 /
main thread: sid #1023 / #100 inserted / #100 before commit / #100 after commit
worker thread #1: sid #1045 / #100 inserted / #100 before commit / #100 after
commit
worker thread #2: sid #1019 / #100 inserted / #100 before commit / #100 after
commit
PL/SQL procedure successfully completed.
SQL> I am getting a different result.
Regards
Raj -
Will there performance improvement over separate tables vs single table with multiple partitions? Is advisable to have separate tables than having a single big table with partitions? Can we expect same performance having single big table with partitions? What is the recommendation approach in HANA?
Suren,
first off a friendly reminder: SCN is a public forum and for you as an SAP employee there are multiple internal forums/communities/JAM groups available. You may want to consider this.
Concerning your question:
You didn't tell us what you want to do with your table or your set of tables.
As tables are not only storage units but usually bear semantics - read: if data is stored in one table it means something else than the same data in a different table - partitioned tables cannot simply be substituted by multiple tables.
Looked at it on a storage technology level, table partitions are practically the same as tables. Each partition has got its own delta store & can be loaded and displaced to/from memory independent from the others.
Generally speaking there shouldn't be too many performance differences between a partitioned table and multiple tables.
However, when dealing with partitioned tables, the additional step of determining the partition to work on is always required. If computing the result of the partitioning function takes a major share in your total runtime (which is unlikely) then partitioned tables could have a negative performance impact.
Having said this: as with all performance related questions, to get a conclusive answer you need to measure the times required for both alternatives.
- Lars -
How to use the Table Function defined in package in OWB?
Hi,
I defined a table function in a package. I am trying to use that in owb using Table function operator. But I came to know that, owb R1 supports only standalone table functions.
Is there any other way to use the table function defined in a package. As like we create synonyms for functions, is there any other way to do this.
I tryed to create synonyms, it is created. But it is showing compilation error. Finally I found that, we can't create synonyms for functions which are defined in packages.
Any one can explain it, how to resolve this problem.
Thank you,
Regards
Gowtham Sen.Hi Marcos,
Thank you for reply.
OWB R1 supports stand alone table functions. Here what I mean is, the table fucntion which is not inculded in any package is a stand alone table function.
for example say sample_tbl_fn is a table function. It is defined as a function.It is a stand alone function. We call this fucntion as "samp_tbl_fn()";
For exampe say sample_pkg is a package. say a function is defined in a package.
then we call that function as sample_pkg.functionname(); This is not a stand alone function.
I hope you understand it.
owb supports stand alone functions.
Here I would like to know, is there any other way to use the functions which are defined in package. While I am trying to use those functions (which are defined in package -- giving the name as packagename.functionname) it is throwing an error "Invalid object name."
Here I would like know, is there any other way to use the table functions which are defined in a package.
Thank you,
Regards,
Gowtham Sen. -
Performance improve using TEZ/HIVE
Hi,
I’m newbie in HDInsight. Sorry for asking simple Questions. I have queries around performance improvement of my HIVE query on File data of 90 GB (15 GB * 6).
We have enabled execution engine has TEZ, I heard the AVRO format improves the speed of execution, Is AVRO SERDE enabled TEZ Queries or do I need upload *.jar files to WASB. I’m using latest version. Any sample Query.
In TEZ, Will ORC Column Format and Avro compression can work together, when we set ORC compression level on hive has
Snappy and LZO ?. Is there any Limitation of Number of columns for ORC tables.
Is there any best compression technique to upload data file to Blob, I mean compress and upload. I used *.gz, which compressed by 1/4<sup>th</sup> of File Size and upload to Blob, but problem *.gz is not split able and it will always
uses less (single ) Mapper or should I use Avro with Snappy Compression . Is the Microsoft Avro Library performs snappy Compression or is there any compress which can be split and compress.
If data structure for file change over time , will there be necessity of reloading older data?. Can existing query works without change in code.
It has been said that TEZ has Real Time Reporting capability , but when I Query 90 GB file (It includes Group By, order by clauses) is taking almost 8 mins of time on 20 nodes, are there any pointers to improve performance further and get the Query result
in Seconds.
Mahender-- Tez is an execution engine, I don't think you need any additional jar file to get AVRO Serde working on Hive when Tez is used. You can used AvroSerDe, AvroContainerInputFormat & AvroContainerOutputFormat to get AVRO working when tez is
used.
-- I tried creating a table with about 220 columns, although the table was empty, I was able to query from the table, how many columns does your table hold?
CREATE EXTERNAL TABLE LargColumnTable02(t1 string,.... t220 string)
PARTITIONED BY(EventDate string) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS ORC LOCATION '/data'
tblproperties("orc.compress"="SNAPPY");
-- You can refer
http://dennyglee.com/2013/03/12/using-avro-with-hdinsight-on-azure-at-343-industries/
Getting Avro data into Azure Blob Storage Section
-- It depends on what data has change , if you are using Hadoop, HBase etc..
-- You will have to monitor your application check node manager logs if there is any pause in execution again. It depends on what you are doing, would suggest open a Support case to investigate further. -
Duplicate Rows In Oracle Pipelined Table Functions
Hi fellow oracle users,
I am trying to create an Oracle piplined table function that contains duplicate records. Whenever I try to pipe the same record twice, the duplicate record does not show up in the resulting pipelined table.
Here's a sample piece of SQL:
/* Type declarations */
TYPE MY_RECORD IS RECORD(
MY_NUM INTEGER
TYPE MY_TABLE IS TABLE OF MY_RECORD;
/* Pipelined function declaration */
FUNCTION MY_FUNCTION RETURN MY_TABLE PIPELINED IS
V_RECORD MY_RECORD;
BEGIN
-- insert first record
V_RECORD.MY_NUM = 1;
PIPE ROW (V_RECORD);
-- insert second duplicate record
V_RECORD.MY_NUM = 1;
PIPE ROW (V_RECORD);
-- return piplined table
RETURN;
END;
/* Statement to query pipelined function */
SELECT * FROM TABLE( MY_FUNCTION ); -- for some reason this only returns one record instead of two
I am trying to get the duplicate row to show up in the select statement. Any help would be greatly appreciated.Can you provide actual output from an SQL*Plus prompt trying this? I don't see the same behavior
SQL> SELECT * FROM V$VERSION;
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for 64-bit Windows: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production
SQL> CREATE TYPE MY_RECORD IS OBJECT(MY_NUM INTEGER);
2 /
Type created.
SQL> CREATE TYPE MY_TABLE IS TABLE OF MY_RECORD;
2 /
Type created.
SQL> CREATE OR REPLACE FUNCTION MY_FUNCTION
2 RETURN MY_TABLE
3 PIPELINED
4 AS
5 V_RECORD MY_RECORD;
6 BEGIN
7 V_RECORD.MY_NUM := 1;
8 PIPE ROW(V_RECORD);
9
10 V_RECORD.MY_NUM := 1;
11 PIPE ROW(V_RECORD);
12
13 RETURN;
14 END;
15 /
Function created.
SQL> SELECT * FROM TABLE(MY_FUNCTION);
MY_NUM
1
1 -
Parallel not working in pipelined table function?
I've found this excelent article titled 'Oracle fast parallel data unload into ASCII file(s)' in this blog: http://jiri.wordpress.com/2009/03/18/oracle-fast-parallel-data-unload-into-ascii-files/
I have compiled the code and created the objects and the directory in my DB
But when I execute :
SELECT *
FROM TABLE(
DATA_UNLOAD(
CURSOR(
SELECT /*+ PARALLEL(A, 2, 1) */
TABLE_NAME || '|' ||
COLUMN_NAME || '|' ||
DATA_TYPE
FROM MYTABLE A
'SAMPLE_SPOOL.TXT',
'DIR_USERS_JIRI',
'Y',
'Y' )
It is suposed to return 2 rows (because of parallel execution), but it just returns 1
Do I have to do something special in order to make parallel pipelined function work
Edited by: igorcb123 on 01-02-2011 01:58 PMIf & Else is wrongly used in the function
FUNCTION F_PS_HIGH_SCHOOL (OLD_HS CHAR)
RETURN
CHAR
IS
NEW_HIGH_SCHOOL CHAR(11);
BEGIN
IF OLD_HS = ' ' THEN NEW_HIGH_SCHOOL := ' ';
ELSE-- Incorrect usage
SELECT
MC_AD_HS_NAME INTO NEW_HIGH_SCHOOL
FROM
XLAT_HIGH_SCHOOL_CODES_2
WHERE
SIS_HS_CODE = OLD_HS;
RETURN NEW_HIGH_SCHOOL;
END IF;
RETURN NEW_HIGH_SCHOOL;
END F_PS_HIGH_SCHOOL; -
Query performance improvement techniques(urgent)
Hi experz,
I am having a business requirement where i have to fill the variable with 59 days(mandatory field).from different regional cubes, these are all compressedcubes, records are almost 45 mlns in a cube when i give selection by default it selects one aggrigate defined on this, but aftr running some time it is going to short dump,if the time for report execution is more than 10 mts its performance is very bad i know! can you guys suggest me how can i improve the performance of this report.
when i gave the same selections in list cube transaction it is saing LSLVCF36 error,message_type_text error;
can you guys help me in this,i ll give full points.
thanks and regards,
veeruHi,
Try these
Go to transaction ST03 > switch to expert mode > from left side menu > and there in system load history and distribution for a particual day > check query execution time.
1. Use different parameters in ST03 to see the two important parameters aggregation ratio and records transferred to F/E to DB selected.
2. Use the program SAP_INFOCUBE_DESIGNS to see the aggregation ratio for the cube. If the cube does not appear in the list of this report, try to run RSRV checks on the cube and aggregates.
3. --- sign is the valuation of the aggregate. You can say -3 is the valuation of the aggregate design and usage. ++ means that its compression is good and access is also more (in effect, performance is good). If you check its compression ratio, it must be good. -- means the compression ratio is not so good and access is also not so good (performance is not so good).The more is the positives...more is useful the aggregate and more it satisfies the number of queries. The greater the number of minus signs, the worse the evaluation of the aggregate. The larger the number of plus signs, the better the evaluation of the aggregate.
if "-----" then it means it just an overhead. Aggregate can potentially be deleted and "+++++" means Aggregate is potentially very useful.
Refer.
http://help.sap.com/saphelp_nw70/helpdata/en/b8/23813b310c4a0ee10000000a114084/content.htm
4. Run your query in RSRT and run the query in the debug mode. Select "Display Aggregates Found" and "Do not use cache" in the debug mode. This will tell you if it hit any aggregates while running. If it does not show any aggregates, you might want to redesign your aggregates for the query.
Also your query performance can depend upon criteria and since you have given selection only on one infoprovider...just check if you are selecting huge amount of data in the report.
5. In BI 7 statistics need to be activated for ST03 and BI admin cockpit to work.
http://help.sap.com/saphelp_nw70/helpdata/en/26/4bc0417951d117e10000000a155106/frameset.htm
/people/vikash.agrawal/blog/2006/04/17/query-performance-150-is-aggregates-the-way-out-for-me
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/docs/library/uuid/1955ba90-0201-0010-d3aa-8b2a4ef6bbb2
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/docs/library/uuid/ce7fb368-0601-0010-64ba-fadc985a1f94
https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/docs/library/uuid/4c0ab590-0201-0010-bd9a-8332d8b4f09c
Thanks,
JituK -
How could we user the table function in a procedure?
In fact, here's an example function that does the same...
TYPE split_tbl IS TABLE OF VARCHAR2(32767);
FUNCTION split (p_list VARCHAR2, p_delim VARCHAR2:=' ') RETURN SPLIT_TBL PIPELINED IS
l_idx PLS_INTEGER;
l_list VARCHAR2(32767) := p_list;
l_value VARCHAR2(32767);
BEGIN
LOOP
l_idx := INSTR(l_list, p_delim);
IF l_idx > 0 THEN
PIPE ROW(SUBSTR(l_list, 1, l_idx-1));
l_list := SUBSTR(l_list, l_idx+LENGTH(p_delim));
ELSE
PIPE ROW(l_list);
EXIT;
END IF;
END LOOP;
RETURN;
END SPLIT;
Maybe you are looking for
-
Can't open PDF files in Firefox 16.0.1
Mac OS 10.6.8, Firefox 16.0.1, PDF Viewer 0.6.39 installed. In Firefox>Preferences>Applications, PDFs are supposed to be handled by the PDF Browser 2.4.4 plug-in for Preview. However, when I try to view a PDF in Firefox, I get this: "We are sorry, bu
-
Unable to create the bluetooth virtual COM port
Hi all I install BS from Toshiba and it seems ok. Bt ir desn´t work. I see all the drivers installed, system devices, etc. No Toshiba BT ports can be seen. Local com ports only show modem port. Try to create a virtual port but get a message "unable t
-
Hallo, must i assign a rfc-destination to a outbound queue? what happens when this is not done? Thanks in advance, Frank
-
hi experts, We faced PO printout problem during our Go Live. We have implemented SAP with new Plant/Company. For all PO forms in existing company are printing fine, but for this new company, we are trying to print PO but it only goes with the spool r
-
Apple Lossless drains my iPod's power!
After doing the battery tests on my Ipod, I've realised that while I can get the full 20 hour battery life from it, if I import songs using Apple Lossless, the battery life is reduced to just 12.5 hours. Does anyone know the reason for this? Does App