Slow Drop Table DDL
Eric Harper, July 15, 2022 - 12:10 pm UTC
Good Morning Connor,
I have had a similar problem, we have to drop about 10K tables a month that are interim staging tables, some drop in 0.2 seconds, while others were taking in a range of 1 - 5 minutes, resulting in a multi-day drop each month. Per your recommendation, I enabled the session trace during the drop of 8 tables, generated 79 MB trace file. Our DB is 300 TB, 19.7 enterprise edition, non-RAC, the dictionary is huge, but still.
Before uploading the trace file, I found a pattern:
* all our slow table drops contained a UNIQUE index
* all our fast table drops had no indexes at all.
(1) Drop table with purge, did not help, we don't use recyclebin.
(2) Truncate table, drop table, did not help, multi-minute. So it's not data related.
(3) Drop any index(es) on the table. --- subsecond
Drop the table --- subsecond
The problem for us was our unique indexes, I'm now checking, during the generation of the drop table statement for any indexes, drop those first, then drop the table itself and my multi-day drops are down to around an hour.
If I had to guess, the presence of a unique index represents the opportunity to introduce referential integrity, this forces the drop ddl down the path of looking at these objects:
X Lock on:
Schema_Name.Table_Name_Being_Dropped
SX Lock on:
Sys.ASSEMBLY$
Sys.CACHE_STATS_1$
Sys.COL$
Sys.COM$
Sys.COMPRESSION_STAT$
Sys.DIANA_VERSION$
Sys.DIR$
Sys.EDITION$
Sys.HISTGRM$
Sys.HIST_HEAD$
Sys.ICOL$
Sys.ICOLDEP$
Sys.IDL_CHAR$
Sys.IDL_SB4$
Sys.IDL_UB1$
Sys.IDL_UB2$
Sys.ILM$
Sys.ILMOBJ$
Sys.ILMPOLICY$
Sys.JAVAOBJ$
Sys.LIBRARY$
Sys.NCOMP_DLL$
Sys.OBJAUTH$
Sys.OBJECT_USAGE
Sys.PROCEDURE$
Sys.SNAP_LOADERTIME$
Sys.SQLTXL$
Sys.SQLTXL_ERR$
Sys.SQLTXL_SQL$
Sys.SUMDELTA$
Sys.SUMPARTLOG$
Sys.TYPE_MISC$
You can see this happening with this SQL, during drop of a table with a UNIQUE index, may need a DBA to run this, if so, ask them for SELECT_CATALOG_ROLE, so you can do it yourself next time.
col oracle_username for a18 head 'Username'
col os_user_name for a12
col process for a12 head 'Process'
col session_id for 99999 head 'SID'
col locked_mode for a4 head 'Lock|Mode'
col object_name45 for a45 head 'Schema.OBJECT_NAME'
col object_type7 for a7 head 'Object|Type'
break on session_id skip 1 on inst_ID
select
a.session_id,
a.oracle_username,
initcap(b.owner) || '.' || b.object_name as object_name45,
replace(replace(replace(replace(replace
(b.object_type,
'TABLE', 'Tbl'),
'INDEX', 'Ix'),
' PARTITION','Part'),
' SUBPARTITION','SbPt'),
'MATERIALIZED VIEW', 'MV') as object_Type7,
a.process,
Case a.locked_mode
When 3 Then ' sX'
When 2 Then ' ss'
When 0 Then 'none'
When 1 Then 'null'
When 6 Then ' X'
When 5 Then ' ssX'
When 4 Then ' s'
Else to_char('.' || a.locked_mode || '?')
End as Locked_Mode
from V$Locked_object a,
dba_objects b
where A.object_id = b.object_id
order by 2, 1, 3, 4 ;
clear breaks
I do not see this overhead of checking during the drop of tables with no indexes.
Cheers,
Eric
July 18, 2022 - 3:43 am UTC
Is that a 79M raw trace or tkprof file? If the tkprof file is less than 10meg, you can email the tkprof file to asktom_us@oracle.com with subject: 9530521900346561794
and we'll take a look.