Skip to Main Content
  • Questions
  • Questions about the COST of function TABLE(....)

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Joe.

Asked: July 21, 2017 - 9:42 am UTC

Last updated: July 25, 2017 - 7:16 am UTC

Version: 11.2.0.4

Viewed 1000+ times

You Asked

Hi Team,
There's a function called SPLIT which was used to split our variable data into multi rows (fields terminated by '|'), for example turn 11|22|33 into 3 rows:11,22 and 33. When we tried to query that table with JOIN, oops, the cost was up to 131K, our customer believed that we should optimize the SQL statement.

HERE is the DEMO:

SQL> create or replace type type_split is table of varchar2(30000);  PLZ NOTICE THAT THE LENGTH IS 30000
  2  /

Type created.

SQL> create or replace function split
  2  (
  3     p_list varchar2,
  4     p_sep varchar2 := ','
  5  )  return type_split pipelined
  6   is
  7     l_idx  pls_integer;
  8     v_list  varchar2(4000) := p_list;
  9  begin
 10     loop
 11        l_idx := instr(v_list,p_sep);
 12        if l_idx > 0 then
 13            pipe row(substr(v_list,1,l_idx-1));
 14            v_list := substr(v_list,l_idx+length(p_sep));
 15        else
 16            pipe row(v_list);
 17            exit;
 18        end if;
 19     end loop;
 20     return;
 21  end split;
 22  /

Function created.

SQL> set linesize 160
SQL> SELECT SUM(SUM_QTY), MAX(SUM_QTY)
  2    FROM (SELECT A.EC_NAME, B.POSITION_NAME, SUM(C.ECQ_NAME) SUM_QTY
  3            FROM (SELECT ROWNUM EC_NUM, A.COLUMN_VALUE EC_NAME
  4                    FROM TABLE(SPLIT('11|22|33|44', '|')) A) A
  5            LEFT JOIN (SELECT ROWNUM POSITION_NUM, B.COLUMN_VALUE POSITION_NAME
  6                        FROM TABLE(SPLIT('11|22|33|44', '|')) B) B
  7              ON A.EC_NUM = B.POSITION_NUM
  8            LEFT JOIN (SELECT ROWNUM ECQ_NUM, C.COLUMN_VALUE ECQ_NAME
  9                        FROM TABLE(SPLIT('11|22|33|44', '|')) C) C
 10              ON A.EC_NUM = C.ECQ_NUM
 11           GROUP BY A.EC_NAME, B.POSITION_NAME);


Execution Plan
----------------------------------------------------------
Plan hash value: 2535028843

----------------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name  | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                         |       |     1 |    13 |       |   131K  (2)| 00:00:06 |
|   1 |  SORT AGGREGATE                          |       |     1 |    13 |       |            |          |
|   2 |   VIEW                                   |       |    54M|   675M|       |   131K  (2)| 00:00:06 |
|   3 |    HASH GROUP BY                         |       |    54M|   306G|       |   131K  (2)| 00:00:06 |
|*  4 |     HASH JOIN RIGHT OUTER                |       |    54M|   306G|    15M|   130K  (1)| 00:00:06 |
|   5 |      VIEW                                |       |  8168 |    15M|       |    29   (0)| 00:00:01 |
|   6 |       COUNT                              |       |       |       |       |            |          |
|   7 |        COLLECTION ITERATOR PICKLER FETCH | SPLIT |  8168 | 16336 |       |    29   (0)| 00:00:01 |
|*  8 |      HASH JOIN OUTER                     |       |   667K|  2564M|    15M|  1627   (1)| 00:00:01 |
|   9 |       VIEW                               |       |  8168 |    15M|       |    29   (0)| 00:00:01 |
|  10 |        COUNT                             |       |       |       |       |            |          |
|  11 |         COLLECTION ITERATOR PICKLER FETCH| SPLIT |  8168 | 16336 |       |    29   (0)| 00:00:01 |
|  12 |       VIEW                               |       |  8168 |    15M|       |    29   (0)| 00:00:01 |
|  13 |        COUNT                             |       |       |       |       |            |          |
|  14 |         COLLECTION ITERATOR PICKLER FETCH| SPLIT |  8168 | 16336 |       |    29   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("A"."EC_NUM"="C"."ECQ_NUM"(+))
   8 - access("A"."EC_NUM"="B"."POSITION_NUM"(+))

Note
-----
   - 'PLAN_TABLE' is old version


Statistics
----------------------------------------------------------
        161  recursive calls
          0  db block gets
        377  consistent gets
          0  physical reads
          0  redo size
        624  bytes sent via SQL*Net to client
        607  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed




Here's my questions:
1) How does oracle generate the execution plan? the TABLE(SPLIT()) is not a heap table, I guess there was no histogram and the result of TABLE(SPLIT()) was resident in PGA (I had found the event 'PGA memory operation') during executions. By the way, if I reduce the length of type named 'type_split' in this case (say from 30000 to 3000), the COST would reduced somehow.
2) Will Adaptive Cursor Sharing available?
3) What do you guys suggest to optimize our query in this case? The COST seems depressed me.

and Connor said...

Rating

  (1 rating)

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

Comments

Joe Huang, July 24, 2017 - 2:32 am UTC

Hi Connor,
Thanks for your reference at https://asktom.oracle.com/pls/apex/f?p=100:11:2291566777905::NO:::

In my case, GTT could be a best solution.

With AS+materialize hit may not suitable in this case, since we just query only 1 time each table.

Adrian Billington's idea of using little utility to tinker with cardinalities with collections is good, but not a silver bullet, bcoz it could only access to nested item.
Anyway, it's a good way of thinking.

If I'm wrong, it would be nice if you could point out.
Thanks again.

Connor McDonald
July 25, 2017 - 7:16 am UTC

Nope - you're on the right track. Things get better in 12.2

More to Explore

Performance

Get all the information about database performance in the Database Performance guide.