sql tuning | calculating logical reads made by a query

·

1 min read

one day a dba reported high resource usage by a query, but it was 'well-optimized' and the runtime was as expected, then what was wrong? logical read was high.

to calculate logical reads made by a query:

DECLARE
    READS NUMBER;
    OUTPUT NUMBER;
    L_SQL VARCHAR2(4000);
    L_MULTIPLIER NUMBER;
BEGIN
    L_SQL := q'[SELECT *
                  FROM ALL_TABLES T, (SELECT 1
                                        FROM DUAL
                                     CONNECT BY LEVEL<=:P_MULTIPLIER)]';
    L_MULTIPLIER := 10000;

    EXECUTE IMMEDIATE 'ALTER SYSTEM FLUSH BUFFER_CACHE';
    EXECUTE IMMEDIATE 'ALTER SYSTEM FLUSH SHARED_POOL';

    SELECT NVL(ST.VALUE, 0) INTO READS
      FROM V$STATNAME S, V$MYSTAT ST
     WHERE ST.STATISTIC# = S.STATISTIC#
           AND S.NAME = 'session logical reads';

    EXECUTE IMMEDIATE L_SQL USING L_MULTIPLIER;

    SELECT NVL((ST.VALUE - READS), 0) INTO OUTPUT
      FROM V$STATNAME S, V$MYSTAT ST
     WHERE ST.STATISTIC# = S.STATISTIC#
           AND S.NAME = 'session logical reads';

    DBMS_OUTPUT.PUT_LINE('Logical reads before: '||READS);
    DBMS_OUTPUT.PUT_LINE('Logical reads after: '||(OUTPUT+READS));
    DBMS_OUTPUT.PUT_LINE('Number of logical reads made by the query: '||OUTPUT);
END;

for this example query, I got the same number of logical reads made when the L_MULTIPLIER was changed, as expected.

L_MULTIPLIER := 100;
Logical reads before: 294064
Logical reads after: 296383
Number of logical reads made by the query: 2319

L_MULTIPLIER := 10000;
Logical reads before: 300532
Logical reads after: 302851
Number of logical reads made by the query: 2319

maybe you can ask your DBAs to check the cache hit ratio and do their magic there.