Friday, July 4, 2014

SQL Tuning

1. SQL Performance Tuning team recommends using COUNT(1) instead COUNT(*) for SQL query performance optimization.

Do not use:
SELECT COUNT(*) FROM master;

Use:
SELECT COUNT(1) FROM master;

2. If you are using more than one table, make sure to use table aliases.

SELECT COUNT(1) FROM master m, detail d WHERE m.id = d.master_id;

3. It is good practice to use table column names in an SQL query. This way the SQL statements will be more readable, but that is not the main reason. Example: If in INSERTstatement you use SELECT * FROM x and at some point you add a new column in table x, SQL will return an error. The third reason why it is better to use table column names is to reduce network traffic

4. In WHERE statements make sure to compare string with string and number with number, for optimal SQL query performance.

Do not use:
SELECT id, apn, charging_class FROM master WHERE id = '4343';

Use:
SELECT id, apn, charging_class FROM master WHERE id = 4343;

5.  Avoid using complex expressions.

Avoid:
WHERE serial_id = NVL(:a1, serial_id)
WHERE NVL(serial_id,-1) = ( 1, etc...).

6. SQL Performance Tuning recommends using CASE statements. It is more efficient to run a single SQL statement, rather than two separate SQL statements.

Do not use:
SELECT COUNT (1) FROM emp WHERE salary <= 1000;
SELECT COUNT (1) FROM emp WHERE salary BETWEEN 1000 AND 2000;

Use:
SELECT COUNT (CASE WHEN salary <= 1000
                   THEN 1 ELSE null END) count_1,
       COUNT (CASE WHEN salary BETWEEN 1001 AND 2000
                   THEN 1 ELSE null END) count_2
  FROM emp;

7. Use UNION ALL instead of UNION, if possible

Do not use:
SELECT id, name FROM emp_bmw
UNION
SELECT id, name FROM emp_bmw_welt

Use:
SELECT id, name FROM emp_bmw
UNION ALL
SELECT id, name FROM emp_bmw_welt

8. SQL Performance Tuning OR vs. IN.

Our tests showed that using IN in WHERE condition is a little faster then using OR.

Do not use:
SELECT * FROM CDRS_NR WHERE RECORD_TYPE = 'MTC' OR  RECORD_TYPE = 'MOC' OR  RECORD_TYPE = 'SMSO';

Use:
SELECT * FROM CDRS_NR WHERE RECORD_TYPE IN ('MTC', 'MOC', 'SMSO')

9. SQL Performance Tuning recommends to use minimal number of sub queries, if possible.

Do not use:
SELECT id, manufacturer, model
  FROM cars
 WHERE price = ( SELECT MAX(price)
                   FROM cars_bmw
               )
   AND year =  ( SELECT MAX(year)
                   FROM cars_bmw
               )

Use:
SELECT id, manufacturer, model
  FROM cars
 WHERE (price, year) = ( SELECT MAX(price), MAX(year)
                           FROM cars_bmw
                       )

10. Using the indexes carefully 

Having indexes on columns is the most common method of enhancing performance, but having too many of them may degrade the performance as well. So, it's very critical to decide wisely about which all columns of a table we should create indexes on. Few common guidelines are:- creating indexes on the columns which are frequently used either in WHERE clause or to join tables, avoid creating indexes on columns which are used only by functions or operators, avoid creating indexes on the columns which are required to changed quite frequently, etc.

11. Using WHERE instead of HAVING 

usage of WHERE clause may take advantage of the index defined on the column(s) used in the WHERE clause.

12. Indexed Scan vs Full Table Scan 

Indexed scan is faster only if we are selecting only a few rows of a table otherwise full table scan should be preferred. It's estimated that an indexed scan is slower than a full table scan if the SQL statement is selecting more than 15% of the rows of the table. So, in all such cases use the SQL hints to force full table scan and suppress the use of pre-defined indexesOkay... any guesses why full table scan is faster when a large percentage of rows are accessed? Because an indexed scan causes multiple reads per row accessed whereas a full table scan can read all rows contained in a block in a single logical read operation.

13. Using ORDER BY for an indexed scan 

the optimizer uses the indexed scan if the column specified in the ORDER BY clause has an index defined on it. It'll use indexed scan even if the WHERE doesn't contain that column (or even if the WHERE clause itself is missing). So, analyze if you really want an indexed scan or a full table scan and if the latter is preferred in a particular scenario then use 'FULL' SQL hint to force the full table scan.


14. Using ROWID and ROWNUM wherever possible

These special columns can be used to improve the performance of many SQL queries. The ROWID search is the fastest for Oracle database and this luxury must be enjoyed wherever possible. ROWNUM comes really handy in the cases where we want to limit the number of rows returned.

15. Optimizing the WHERE clause 

There are many cases where index access path of a column of the WHERE clause is not used even if the index on that column has already been created. Avoid such cases to make best use of the indexes, which will ultimately improve the performance. Some of these cases are: COLUMN_NAME IS NOT NULL (ROWID for a null is not stored by an index), COLUMN_NAME NOT IN (value1, value2, value3, ...), COLUMN_NAME != expression, COLUMN_NAME LIKE'%pattern' (whereas COLUMN_NAME LIKE 'pattern%' uses the index access path), etc. Usage of expressions or functions on indexed columns will prevent the index access path to be used. So, use them wisely!

16. Using Bind Variables, Stored Procs, and Packages 

Using identical SQL statements (of course wherever applicable) will greatly improve the performance as the parsing step will get eliminated in such cases. So, we should use bind variables, stored procedures, and packages wherever possible to re-use the same parsed SQL statements.

Full Table Scans can be good when:

Used on a small table (< 500 rows)
Used in a query returning more than a few percent of the rows in a table
Used in a Sort-Merge or Hash join, but only when these join methods are intended.

Full Table Scans are bad when:

Used on a large table where indexed or hash cluster access is preferred.
Used on a medium-large table (> 500 rows) as the outer table of a Nested Loop join.
Used on a medium-large table (> 500 rows) in a Nested Sub-Query.
Used in a Sort-Merge or Hash join when a Nested Loop join is preferred.



Thursday, July 3, 2014

Performance Analysis

Checks to be performed at the machine level

run queue should be ideally not more than the number of CPU’s on the machine. At the maximum it should never be more than twice the number of CPU’s.This is denoted by the column ‘r’ in the vmstat output shown below vmstat – 5

$vmstat 5
                                                 






CPU idle% < 10 ( id column) could indicate a machine that is having CPU resource issues

Note: How to find number of CPU’s on a LINUX machine?

cat /proc/cpuinfo |grep -w “processor” |wc –l

Swap columns si and so should ideally be 0 to indicate no swapping activity

$ free -m           







We should be looking at the free and used values in the row denoted by “-/+ buffers/cache”

The ‘top’ command will help us identify the load average on the machine as well as any process that is consuming excessive CPU

$top

















A load average greater than 5 or 10 could indicate a heavily utilized machine

CPU information for each CPU is also provided via the top command as well as information on the physical as well as virtual Memory that is available on the machine.

Information on the top CPU as well as Memory consuming processes is also provided along with the Process ID (PID). In a later section we will use this PID as a parameter for a SQL query to identify the SQL being executed by the same CPU consuming process.

Identify if any single PID is constantly appearing in the top output

The iowait column can also help us identify if there’s any resource contention from the IO perspective.

A value above 40-50% would indicate I/O resource issues and require further investigation into the process that is causing this high I/O – or it could indicate a case of inefficient disk sub system or file layout in the database.

We can also view the state of the machine at a particular time of the day by running the sar command which will provide the system utilisation report since 12:00 AM on that particular day.

We can use the sar command to identify the machine state even for a particular day of the month
For example sar -f /var/log/sa/sa03 will report for the 3rd of the month

Checks to be performed at the database level

Identify with the user if the problem is a slow response or a hanging situation.

Establish a connection via SQL*NET using a non SYSDBA account to confirm that the listener is accepting client connections and the hanging is not due to the archive area getting 100% full.

Examine the alert log file for ‘Checkpoint Not Completed’ errors recorded at the time the performance problem is reported – this could indicate an I/O contention issue or inadequately sized redo log files which can also cause an application hang while the checkpoint completes.

Ensure that the mount point on which the Oracle software is not 100% full or the disks holding the controlfiles are also not 100% full.

Check the listener.log file if it exists and ensure that it is not > 2GB – on some Operating Systems like LINUX, there is a file size upper limit for the listener.log file after which client connections will not be accepted by the listener.

Check for locked sessions (see script check_lock.sql).

If a PID has been identified as a top CPU consuming process, check the SQL being executed by that particular PID (see script check_pid_sql.sql)

If the user provides a particular SID where a possible performance issue exists, check the SQL being executed by that SID ( see script check_sid_sql.sql)

If the user provides a particular Oracle username where a possible performance issue exists, check the SQL being executed by that Oracle user ( see script check_username_sql.sql)

Very Important – check the major wait events in the database (see script wait_events.sql)

check the SID along with the events that each SID is waiting on (see script wait_events_sid.sql) – based on the SID, the SQL being executed by the waiting sessions can be obtained as well ( see script check_sid_sql.sql)

Check for any sessions continuously waiting for on a particular latch (see script check_latch.sql)

What has changed?

Is there a measurable baseline regarding the “problem” query – when did it last perform well?
Has the database been upgraded recently?
Has any modifications been done to the database in terms of init.ora parameters?
Have any new indexes been added to the table or has the table structure changed?
Has the platform or database version changed?
Is this a period of unusual business activity? – like a monthly data load or one-off batch job

check_pid_sql.sql

SET PAGESIZE 500
set long 500000
set head off
select
       s.username su,
       substr(sa.sql_text,1,540) txt
from v$process p,
     v$session s,
     v$sqlarea sa
where    p.addr=s.paddr
and      s.username is not null
and      s.sql_address=sa.address(+)
and      s.sql_hash_value=sa.hash_value(+)
and spid=;

check_sid_sql.sql

SET PAGESIZE 500
PROMPT=============================================================
PROMPT Current SQL statement this session executes
PROMPT=============================================================
col sql_text for a70 hea "Current SQL"
select q.sql_text
from v$session s
,    v$sql     q
WHERE s.sql_address = q.address
and   s.sql_hash_value + DECODE
                 (SIGN(s.sql_hash_value), -1, POWER( 2, 32), 0) = q.hash_value
AND   s.sid= ;

check_username_sql.sql

set long 500000
SET PAGESIZE 500
select
       s.username su,
       substr(sa.sql_text,1,540) txt
from v$process p,
     v$session s,
     v$sqlarea sa
where    p.addr=s.paddr
and      s.username is not null
and      s.sql_address=sa.address(+)
and      s.sql_hash_value=sa.hash_value(+)
and s.username=upper('&username');

check_lock.sql

set linesize 500
SET PAGESIZE 500
col waiting_session format 99999 heading 'Waiting|Session'
col holding_session format 99999 heading 'Holding|Session'
col mode_held format a20 heading 'Mode|Held'
col mode_requested format a20 heading 'Mode|Requested'
col lock_type format a20 heading 'Lock|Type'
prompt blocked objects from V$LOCK and SYS.OBJ$

set lines 132
col BLOCKED_OBJ format a35 trunc

select /*+ ORDERED */
    l.sid
,   l.lmode
,   TRUNC(l.ctime/60) min_blocked
,   u.name||'.'||o.NAME blocked_obj
from (select *
      from v$lock
      where type='TM'
      and sid in (select sid
                  from v$lock
                  where block!=0)) l
,     sys.obj$ o
,     sys.user$ u
where o.obj# = l.ID1
and   o.OWNER# = u.user#
;

prompt blocked sessions from V$LOCK

select /*+ ORDERED */
   blocker.sid blocker_sid
,  blocked.sid blocked_sid
,  TRUNC(blocked.ctime/60) min_blocked
,  blocked.request
from (select *
      from v$lock
      where block != 0
      and type = 'TX') blocker
,    v$lock        blocked
where blocked.type='TX'
and blocked.block = 0
and blocked.id1 = blocker.id1
;


prompt blockers session details from V$SESSION

set lines 132
col username format a10 trunc
col osuser format a12 trunc
col machine format a15 trunc
col process format a15 trunc
col action format a50 trunc

SELECT sid
,      serial#
,      username
,      osuser
,      machine
FROM v$session
WHERE sid IN (select sid
      from v$lock
      where block != 0
      and type = 'TX')
;

wait_events.sql

SELECT count(*), event FROM v$session_wait
WHERE wait_time = 0
AND event NOT IN
('smon timer','pmon timer','rdbms ipc message',
'SQL*Net message from client')
GROUP BY event ORDER BY 1 DESC
;

wait_events_sid.sql

col username format a12
col sid format 9999
col state format a15
col event format a45
col wait_time format 99999999
set pagesize 800
set linesize 800
select s.sid, s.username, se.event
from v$session s, v$session_wait se
where s.sid=se.sid
and se.event not like 'SQL*Net%'
and se.event not like '%rdbms%'
and s.username is not null
order by 3;

check_latch.sql

select count(*), name latchname from v$session_wait, v$latchname
where event='latch free' and state='WAITING' and p2=latch#
group by name order by 1 desc;


Tuesday, July 1, 2014

ORA-01194: file 1 needs more recovery to be consistent

Method 1:

1) Start the database in mount state

SQL> startup mount;

2) Recover the database.

SQL> recover database;

If you come across below error

ORA-00283: recovery session canceled due to errors
ORA-01610: recovery using the BACKUP CONTROLFILE option must be done
 
ORA-01547: warning: RECOVER succeeded but OPEN RESETLOGS would get error below
ORA-01194: file 1 needs more recovery to be consistent
ORA-01110: data file 1: ‘D:\ORACLE\PRODUCT\10.2.0\ORADATA\DBTEST\SYSTEM01.DBF’

then, do the following

1)
SQL> recover database using backup controlfile until cancel;
ORA-00279: change 766152 generated at 03/16/2013 12:12:04 needed for thread 1
ORA-00289: suggestion :
/u01/app/oracle/flash_recovery_area/DUPDB/archivelog/2013_03_16/o1_mf_1_14_%u_.arc
ORA-00280: change 766152 for thread 1 is in sequence #14

Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
/u01/app/oracle/flash_recovery_area/ORCL/archivelog/2013_03_14/o1_mf_1_10_8n43no4v_.arc
ORA-00310: archived log contains sequence 10; sequence 14 required
ORA-00334: archived log:
'/u01/app/oracle/flash_recovery_area/ORCL/archivelog/2013_03_14/o1_mf_1_10_8n43no4v_.arc'

ORA-01547: warning: RECOVER succeeded but OPEN RESETLOGS would get error below
ORA-01195: online backup of file 1 needs more recovery to be consistent
ORA-01110: data file 1:
'/u01/app/oracle/oradata/DUPDB/datafile/o1_mf_system_7qm3ck4o_.dbf'

2)
SQL> recover database using backup controlfile until cancel;
ORA-00279: change 766152 generated at 03/16/2013 12:12:04 needed for thread 1
ORA-00289: suggestion :
/u01/app/oracle/flash_recovery_area/DUPDB/archivelog/2013_03_16/o1_mf_1_14_%u_.arc
ORA-00280: change 766152 for thread 1 is in sequence #14

Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
/u01/app/oracle/flash_recovery_area/ORCL/archivelog/2013_03_14/o1_mf_1_11_8n43qq5j_.arc
ORA-00310: archived log contains sequence 11; sequence 14 required
ORA-00334: archived log:
'/u01/app/oracle/flash_recovery_area/ORCL/archivelog/2013_03_14/o1_mf_1_11_8n43qq5j_.arc'

ORA-01547: warning: RECOVER succeeded but OPEN RESETLOGS would get error below
ORA-01195: online backup of file 1 needs more recovery to be consistent
ORA-01110: data file 1:
'/u01/app/oracle/oradata/DUPDB/datafile/o1_mf_system_7qm3ck4o_.dbf'

3)
SQL> recover database using backup controlfile until cancel;
ORA-00279: change 766152 generated at 03/16/2013 12:12:04 needed for thread 1
ORA-00289: suggestion :
/u01/app/oracle/flash_recovery_area/DUPDB/archivelog/2013_03_16/o1_mf_1_14_%u_.arc
ORA-00280: change 766152 for thread 1 is in sequence #14

Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
/u01/app/oracle/flash_recovery_area/ORCL/archivelog/2013_03_16/o1_mf_1_14_8n875owh_.arc
ORA-00279: change 769526 generated at 03/16/2013 12:48:13 needed for thread 1
ORA-00289: suggestion :
/u01/app/oracle/flash_recovery_area/DUPDB/archivelog/2013_03_16/o1_mf_1_15_%u_.arc
ORA-00280: change 769526 for thread 1 is in sequence #15
ORA-00278: log file
'/u01/app/oracle/flash_recovery_area/ORCL/archivelog/2013_03_16/o1_mf_1_14_8n875
owh_.arc' no longer needed for this recovery

Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
cancel
Media recovery cancelled.

3) Open the database in resetlog mode

SQL> alter database open resetlogs;

4) Check the status

SQL> select instance_name, status from v$instance;

INSTANCE_NAME    STATUS
------------------------   -------------
DUPDB                  OPEN

SQL> select name, open_mode from v$database;

NAME      OPEN_MODE
----------    ------------------
DUPDB     READ WRITE


Method 2:

SQL> shutdown immediate
ORA-01109: database not open
Database dismounted.
ORACLE instance shut down.

SQL> startup mount
ORACLE instance started.

Total System Global Area  530288640 bytes
Fixed Size                  2131120 bytes
Variable Size             310381392 bytes
Database Buffers          209715200 bytes
Redo Buffers                8060928 bytes
Database mounted.

SQL> ALTER SYSTEM SET "_allow_resetlogs_corruption"= TRUE SCOPE = SPFILE;
SQL> ALTER SYSTEM SET undo_management=MANUAL SCOPE = SPFILE;

SQL> shutdown immediate
ORA-01109: database not open
Database dismounted.
ORACLE instance shut down.

SQL> startup mount
ORACLE instance started.

Total System Global Area  530288640 bytes
Fixed Size                  2131120 bytes
Variable Size             310381392 bytes
Database Buffers          209715200 bytes
Redo Buffers                8060928 bytes
Database mounted.

SQL> alter database open resetlogs;

Database altered.

SQL> CREATE UNDO TABLESPACE undo1 datafile '<ora_data_path>undo1_1.dbf' size 200m autoextend on maxsize unlimited;

Tablespace created.

SQL> ALTER SYSTEM SET undo_tablespace = undo1 SCOPE=spfile;
System altered.

SQL> alter system set undo_management=auto scope=spfile;
System altered.

SQL> shutdown immediate

SQL> startup

ORA-1652 unable to extend table by 128 in tablespace

I have been getting the ORA-1652 errors, and I have no more disk to allocate to my TEMP tablespace:

Tue Dec 23 07:38:16 2008
ORA-1652: unable to extend temp segment by 128 in tablespace TEMP
Tue Dec 23 07:51:11 2008
ORA-1652: unable to extend temp segment by 128 in tablespace TEMP

I have waited for SMON to clean out the un-used TEMP segments. How do I remove the temp segments?

Normally, you would just add disk to TEMP to avoid the ORA-1652 error, but you can also wait for SMON to clean-up the TEMP segment.

1.  Identify temporary datafile details :
  
SYS> select file_name , TABLESPACE_NAME from DBA_TEMP_FILES;

FILE_NAME                                           TABLESPACE_NAME
-------------------------------------------------------    ------------------------------
/oracle_backup/test/TEST/temp01.dbf     TEMP

2.  Check if there is any space available in temporary tablespace (segment)

SYS>SELECT A.tablespace_name tablespace, D.mb_total,
        SUM (A.used_blocks * D.block_size) / 1024 / 1024 mb_used,
        D.mb_total - SUM (A.used_blocks * D.block_size) / 1024 / 1024 mb_free
        FROM     v$sort_segment A,
        (
        SELECT   B.name, C.block_size, SUM (C.bytes) / 1024 / 1024 mb_total
        FROM     v$tablespace B, v$tempfile C
        WHERE    B.ts#= C.ts#
        GROUP BY B.name, C.block_size
        ) D
        WHERE    A.tablespace_name = D.name
        GROUP by A.tablespace_name, D.mb_total;
  
   TABLESPACE        MB_TOTAL    MB_USED    MB_FREE
   ---------------------    ----------------    --------------    -------------
   TEMP                              54              42              12

(in above case out of 54 MB only 12 MB is free)

3.  Temporary fix

a) Resize temporary file as 

SQL> alter database tempfile  ‘/u01/oradata/VIS11i/temp01.dbf’ RESIZE 3072M;

or

b) Add temp datafile to temporary tablespace as

SQL> alter tablespace temp add tempfile  ‘/u01/oradata/VIS11i/temp02.dbf’ SIZE 1024M;

Root Cause Analysis

1.  Identify temp segment usages per session

Temp segment usage per session.

SQL> SELECT   S.sid || ',' || S.serial# sid_serial, S.username, S.osuser, P.spid, S.module,
P.program, SUM (T.blocks) * TBS.block_size / 1024 / 1024 mb_used, T.tablespace,
COUNT(*) statements
FROM     v$sort_usage T, v$session S, dba_tablespaces TBS, v$process P
WHERE    T.session_addr = S.saddr
AND      S.paddr = P.addr
AND      T.tablespace = TBS.tablespace_name
GROUP BY S.sid, S.serial#, S.username, S.osuser, P.spid, S.module,
P.program, TBS.block_size, T.tablespace
ORDER BY mb_used;

2. Identify temp segment usages per statement

Temp segment usage per statement

SELECT  S.sid || ',' || S.serial# sid_serial, S.username, Q.hash_value, Q.sql_text,
T.blocks * TBS.block_size / 1024 / 1024 mb_used, T.tablespace
FROM    v$sort_usage T, v$session S, v$sqlarea Q, dba_tablespaces TBS
WHERE   T.session_addr = S.saddr
AND     T.sqladdr = Q.address
AND     T.tablespace = TBS.tablespace_name
ORDER BY mb_used;

Depending on outcome of temp segment usage per session and per statement focus on problematic session/statement.


For Troubleshooting:

1
select sql_id,max(TEMP_SPACE_ALLOCATED)/(1024*1024*1024) gig
from DBA_HIST_ACTIVE_SESS_HISTORY
where
sample_time > sysdate-2 and
TEMP_SPACE_ALLOCATED > (4*1024*1024*1024)
group by sql_id order by sql_id;

SQL_ID                      GIG
----------------------          --------------------
4q9b2jga61n6s              4.94921875
ay1rf7kr04nkd               4.96972656
b6xhw95dpzvvs             4.89355469

This gives the sql_id and maximum allocated temp space of any queries that ran in the past two days and exceeded 4 gigabytes of temp space.

2
Oracle 11g has a new view called DBA_TEMP_FREE_SPACE that displays information about temporary tablespace usage.

SQL> SELECT * FROM dba_temp_free_space;

TABLESPACE_NAME        TABLESPACE_SIZE   ALLOCATED_SPACE   FREE_SPACE
------------------------------      --------------------------  ----------------------------    -----------------
TEMP                                        56623104               56623104        55574528

DBA_TEMP_FREE_SPACE shows bytes which are free and also which are allocated but are available for reuse

SQL> select tablespace_name, bytes_used, bytes_free from v$temp_space_header group by tablespace_name;

TABLESPACE_NAME      BYTES_USED  BYTES_FREE
------------------------------    ------------------  ------------------
TEMP                              56623104                  0

V$TEMP_SPACE_HEADER shows total free bytes (allocated but available for reuse are not shown here)

3
For Oracle 8 and above, the following query will return all users and their SIDs which are doing a sort:

SELECT  b.tablespace, b.segfile#, b.segblk#, b.blocks, a.sid, a.serial#, a.username, a.osuser, a.status
FROM  v$session a,v$sort_usage b WHERE a.saddr = b.session_addr
ORDER BY b.tablespace, b.segfile#, b.segblk#, b.blocks;

You will receive the following:
                                                                                                                  
                            File     Block                                                                                   
Tablespace Name    ID        ID      Blocks     SID    SERIAL# USERNAME     OSUSER    STATUS 
-----------------------  ------  ---------      ----------  -------  ---------- ------------------   -----------------  -----------
TEMP                     4        22        289      15       1966       SCOTT       usupport     ACTIVE

4
Here are various scripts which helps in determining who's using the TEMP tablespace.

a)
SQL>select a.inst_id,b.Total_MB, b.Total_MB - round(a.used_blocks*8/1024) Current_Free_MB,       
round(used_blocks*8/1024) Current_Used_MB, round(max_used_blocks*8/1024)            
Max_used_MB from gv$sort_segment a,  (select round(sum(bytes)/1024/1024) Total_MB from dba_temp_files ) b;








b)
SQL> SELECT a.username, a.sid, a.serial#, a.osuser, b.tablespace, b.blocks, c.sql_text
FROM gv$session a, gv$tempseg_usage b, gv$sqlarea c
WHERE a.saddr = b.session_addr
AND c.address= a.sql_address
AND c.hash_value = a.sql_hash_value
ORDER BY b.tablespace, b.blocks;

c)
SQL> select s.sid, s.osuser, s. process, s.sql_id, tmp.segtype, ((tmp.blocks*8)/1024)MB, tmp.tablespace
from gv$tempseg_usage tmp, gv$session s
where tmp.session_num=s.serial# and segtype in ('HASH','SORT')
order by blocks desc;

d)
SQL> select sql_id,sum(blocks) from gv$tempseg_usage group by sql_id order by 2 desc;