2016/11/29

How much redo data does you query generate (not about delayed block cleanup)

I want to show a tiny effect of materializing factored subquery, which can lead to huge redo generation.
It is also a good time to taste new feature of defining PL/SQL function in the WITH clause. But it is used here only for convenience.

So, let's check how much redo is generated for materializing just one row and just one time

SQL> with function calc(p_in in number) return number
  2  is
  3    res number;
  4  begin
  5    with a as (select /*+ materialize */ 1 c1 from dual)
  6    select calc.p_in + c1 into res from a;
  7    return res;
  8  end;
  9  select calc(1) from dual;
 10  /

Statistics
----------------------------------------------------------
          3  recursive calls
          8  db block gets
          5  consistent gets
          1  physical reads
        572  redo size
        357  bytes sent via SQL*Net to client
        499  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

Nothing to worry about.
But what if you have some PL/SQL function, which employs materialization, and this function is called for each 100K rows output of your report query.

SQL> with function calc(p_in in number) return number
  2  is
  3    res number;
  4  begin
  5    with a as (select /*+ materialize */ 1 c1 from dual)
  6    select calc.p_in + c1 into res from a;
  7    return res;
  8  end;
  9  select calc(rownum) from dual connect by level <=1e5;
 10  /

Statistics
----------------------------------------------------------
     300001  recursive calls
     802222  db block gets
     500000  consistent gets
     100000  physical reads
   57171620  redo size
     611083  bytes sent via SQL*Net to client
        708  bytes received via SQL*Net from client
         21  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
     100000  rows processed

Things become much more interesting. And it is just for one row stored in the temporary table.

One question remains, what exactly causes redo generation. Unfortunately, SQL Trace does not show anything about materialization. But doing the following run, I can infer that redo data is generated for DDL part of operation only.

SQL> with function calc(p_in in number) return number
  2  is
  3    res number;
  4  begin
  5    with a as (select /*+ materialize */ 1 c1 from dual connect by level<=1e5)
  6    select calc.p_in + sum(c1) into res from a;
  7    return res;
  8  end;
  9  select calc(1) from dual;
 10  /

Statistics
----------------------------------------------------------
          5  recursive calls
        161  db block gets
        157  consistent gets
        152  physical reads
        572  redo size
        359  bytes sent via SQL*Net to client
        499  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

So, materialization feature sometimes is very useful, but it has to be applied with caution.

No comments: