Skip to Main Content
  • Questions
  • How to calculate blocks remaining from Parallel Longops

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Mark.

Asked: March 05, 2020 - 8:42 pm UTC

Last updated: February 03, 2022 - 5:34 am UTC

Version: 12

Viewed 1000+ times

You Asked

I would like to know how to calculate blocks, or time remaining for a parallel table copy.
(What's the answer to a previous reviewer's comments below)
Perhaps there is a way to calculate the blocks written which have not yet been committed yet?


TIME_REMAINING not useful for parallel full table scan?
February 11, 2011 - 1:34 am UTC


Reviewer: Kim Berg Hansen from Middelfart, Denmark

Sorry, Tom - I must not have been all clear :-)

Yes, I am aware that Oracle did the math for me in the TIME_REMAINING column of the view. And the TIME_REMAINING can be calculated independent of what the "unit of work" is, since TOTALWORK and SOFAR is the same unit. So the unit could be "lightyears" or "kilometers" - no matter for the TIME_REMAINING column.

My scenario was parallel full table scan with three child processes each doing "chunks" of rowid range scans. The TIME_REMAINING can tell me how long time is approximately left of EACH of the chunks of rows - but it cannot tell me how many "chunks" are left to scan...

What I tried to estimate was this:

I started the scan at 12 noon. After my table scan had been running for half an hour, I selected gv$sesssion_longops for the sids of the three processes. There were 17 entries in gv$session_longops after half an hour. The sum of TOTALWORK of these 17 entries was about 1.6 million and the units said "blocks". The table was 6.5 million blocks, and therefore I estimated that the parallel full table scan must be about 25% done, and the scan would therefore finish at 2 pm having scanned 6.5 million blocks in about 68 "chunks".

But in reality the scan did not finish until 8 pm having rowid range scanned 258 "chunks" and the sum of TOTALWORK of those 258 entries in gv$session_longops was 26 million.

Thus I concluded that the estimate I did at 12:30 pm was terribly wrong :-) And since the factor of 4 immediately stared me in the eye, I took a wild guess that the programmer who wrote the parallel table scan code perhaps was hardcoding blocksize of 2K in his calls to dbms_application_info.set_session_longops? It was the more comfortable guess for me, since I did not wish to believe that Oracle actually scanned each of the 6.5 million blocks 4 times :-)

But is there another way of guesstimating how much work is left for a parallel full table scan using rowid range scans? If I had another way then I would not have to worry about blocksize in longops :-)

Thanks for your time, as always.

and Connor said...

So here's a potential option you could explore - I'll start with big table that we can scan in parallel


SQL> create table bigtab as
  2  select d.* from dba_objects d,
  3   ( select 1 from dual connect by level <= 1000 );

Table created.

SQL>
SQL> select bytes from dba_segments
  2  where segment_name = 'BIGTAB';

     BYTES
----------
1.3355E+10

SQL>
SQL> select bytes/1024/1024/1024 from dba_segments
  2  where segment_name = 'BIGTAB';

BYTES/1024/1024/1024
--------------------
             12.4375

SQL> select blocks from user_tables
  2  where table_name = 'BIGTAB';

    BLOCKS
----------
   1622079


Now I'm going to scan it in parallel and see what we can glean from the timings etc

SQL> set timing on
SQL> select /*+ parallel(8) */ owner, sum(object_id)
  2  from bigtab
  3  group by owner;

...
...


Whilst that was running, I took a look at v$session_longops - here's some sample data

SQL> select * from v$session_longops
  2  where username = 'MCDONAC'
  3  @pr
==============================
SID                           : 1109
SERIAL#                       : 52999
OPNAME                        : Rowid Range Scan
TARGET                        : MCDONAC.BIGTAB
TARGET_DESC                   :
SOFAR                         : 9853
TOTALWORK                     : 15568
UNITS                         : Blocks
START_TIME                    : 03-FEB-22
LAST_UPDATE_TIME              : 03-FEB-22
TIMESTAMP                     :
TIME_REMAINING                : 5
ELAPSED_SECONDS               : 7
CONTEXT                       : 0
MESSAGE                       : Rowid Range Scan:  MCDONAC.BIGTAB: 9853 out of 15568 Blocks done
USERNAME                      : MCDONAC
SQL_ADDRESS                   : 00007FFECCABF580
SQL_HASH_VALUE                : 364932852
SQL_ID                        : 6a4r6pnaw0vrn
SQL_PLAN_HASH_VALUE           : 3136705186
SQL_EXEC_START                : 03-FEB-22
SQL_EXEC_ID                   : 16777220
SQL_PLAN_LINE_ID              : 8
SQL_PLAN_OPERATION            : TABLE ACCESS
SQL_PLAN_OPTIONS              : FULL
QCSID                         : 124
CON_ID                        : 3
==============================
SID                           : 737
SERIAL#                       : 17228
OPNAME                        : Rowid Range Scan
TARGET                        : MCDONAC.BIGTAB
TARGET_DESC                   :
SOFAR                         : 9604
TOTALWORK                     : 15568
UNITS                         : Blocks
START_TIME                    : 03-FEB-22
LAST_UPDATE_TIME              : 03-FEB-22
TIMESTAMP                     :
TIME_REMAINING                : 5
ELAPSED_SECONDS               : 7
CONTEXT                       : 0
MESSAGE                       : Rowid Range Scan:  MCDONAC.BIGTAB: 9604 out of 15568 Blocks done
USERNAME                      : MCDONAC
SQL_ADDRESS                   : 00007FFECCABF580
SQL_HASH_VALUE                : 364932852
SQL_ID                        : 6a4r6pnaw0vrn
SQL_PLAN_HASH_VALUE           : 3136705186
SQL_EXEC_START                : 03-FEB-22
SQL_EXEC_ID                   : 16777220
SQL_PLAN_LINE_ID              : 8
SQL_PLAN_OPERATION            : TABLE ACCESS
SQL_PLAN_OPTIONS              : FULL
QCSID                         : 124
CON_ID                        : 3
==============================
...
...  (8 rows in total)
...

PL/SQL procedure successfully completed.



As you've pointed out, there is nothing directly in there that says "Hey, this is how long things are going to take"...but we can get some clues using the info that is there.

We can the blocks being scanned by a parallel worker is 15568 ("Rowid Range Scan: MCDONAC.BIGTAB: 9604 out of 15568 Blocks done").

We know that there are 1622079 in the table from USER_TABLES, so from these two things we can deduce:

SQL> select 1622079 / 15568 from dual;

1622079/15568
-------------
   104.193153


there will need to be about 104 scans done. The time elapsed / time remaining figures add to 12 seconds (I deliberately put this table on an old IDE drive to make it easy to monitor) which means total scanning time is:

SQL> select 104*12 from dual;

    104*12
----------
      1248


and we have 8 parallel workers going at this concurrently, which means the estimated time is:

SQL> select 1248 / 8 from dual;

    1248/8
----------
       156


So at a guess, we think this will take around 2mins36s to complete. Lets see what really happened:

SQL> select /*+ parallel(8) */ owner, sum(object_id)
  2  from bigtab
  3  group by owner;

OWNER                          SUM(OBJECT_ID)
------------------------------ --------------
SYS                                2.9489E+12
MYUSER                              932761000
DVF                                1595229000
ORDSYS                             3.5752E+10
...

49 rows selected.

Elapsed: 00:02:53.18


So I think we did pretty well there.

Clearly as queries get more complicated, this math will break down because the results of this group by could easily be the input to a join, which is the input to another aggregation etc etc... and all of that takes time...




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.