Skip to Main Content
  • Questions
  • SQL Query optimization : is scalar subqueries killing the performance?

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, prashant.

Asked: July 21, 2018 - 1:25 pm UTC

Last updated: July 23, 2018 - 7:23 am UTC

Version: 12c

Viewed 1000+ times

You Asked

I need help on query optimization.

The below-mentioned query is just a sample. Actual query has 50+ scalar subqueries. Base table table_xyz has over 5 million records.

SELECT 
    id,
    seq,
    (
        SELECT
            function_abc(t.id,t.seq,115501)
        FROM
            dual
    ) AS txt_dosage_comments,
    (
        SELECT
            function_abc(t.id,t.seq,115502)
        FROM
            dual
    ) AS fld_txt_total_therapy_duration

FROM
    table_xyz t;


function_abc() reads data from another table which has 100million records. table1 has been indexed on (id, seq, field_id, language) fields. There can be multiple records across the rows for one (id, seq) pair that's why there is a loop to concatenate them and make a string.

This is what function looks like :
FUNCTION function_abc (
        pi_id     int,
        pi_seq    int,
        pi_field_id   int
    ) RETURN CLOB AS
        l_result   CLOB := NULL;
    BEGIN
        FOR rec IN (
            SELECT
                text
            FROM
table_1
            WHERE
                id = pi_id
                AND   seq = pi_seq
                AND   language = '001'
                AND   field_id = pi_field_id
            ORDER BY
                seq
        ) LOOP
            l_result := concat(l_result,rec.text);
        END LOOP;

        RETURN l_result;
    END;

and Connor said...

Maybe it is a performance issue...maybe its not. You've not really given us any metrics or measurements to work with.

I will say though - perhaps you don't want any function at all? This looks like it could be written as:

SELECT 
    id,
    seq,
    listagg(case when seq = 115501 then text end) within group ( order by seq ) txt_dosage_comments
    listagg(case when seq = 115502 then text end) within group ( order by seq ) fld_txt_total_therapy_duration
FROM
    table_xyz t,
    ( select *
      from   table_1 
      where  language = '001'
      and    seq in (115501,115502)
    ) t1
where t.id =  t1.id(+)
group by id,seq


or similar.

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

More to Explore

Performance

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