Monday, August 4, 2025

How to Identify and Manage the Largest Objects in Your Oracle EBS Database

 

Title: How to Identify and Manage the Largest Objects in Your Oracle EBS Database

Introduction

Database size can be a critical factor for performance and stability, especially in a complex and high-volume environment like Oracle E-Business Suite (EBS). A growing database can lead to slower queries, longer backup times, and increased storage costs. One of the most effective ways to manage database growth is to identify which tables and objects are consuming the most space.

In this blog post, we'll walk you through how to use simple yet powerful SQL queries to find the largest objects in your Oracle EBS database. We'll start with a basic query and then move on to a more comprehensive one that provides a detailed breakdown of space usage, which is essential for effective database management.


Step 1: The Quick and Simple Approach - Find the Top 10 Largest Objects

If you just need a quick overview of the biggest segments in your entire database, this query is your best friend. It lists the top 10 largest objects (tables, indexes, LOBs, etc.) in terms of raw size.

SQL
SELECT *
FROM (
  SELECT
    SEGMENT_NAME,
    SEGMENT_TYPE,
    BYTES / 1024 / 1024 / 1024 AS GB,
    TABLESPACE_NAME
  FROM DBA_SEGMENTS
  ORDER BY BYTES DESC
)
WHERE ROWNUM <= 10;

What this query does:

  • It queries the DBA_SEGMENTS view, which contains information about all segments in the database.

  • It sorts all segments by size (BYTES) in descending order.

  • The ROWNUM <= 10 clause limits the output to just the top 10 rows.

  • The BYTES column is converted to gigabytes (GB) for easy reading.

This is a great starting point, but it doesn't tell you the whole story, especially in an EBS database where a single table might have multiple indexes and LOB segments.


Step 2: The Detailed Approach - A Comprehensive Breakdown for EBS

In an EBS environment, it's more useful to know which tables (including all their associated indexes and LOBs) are taking up the most space. This next query provides a more comprehensive view by grouping all related segments under their parent table.

SQL
WITH tab_size AS (
  SELECT
    owner,
    table_name,
    SUM(total_bytes) total_bytes,
    SUM(tab_bytes) tab_bytes,
    SUM(ind_bytes) ind_bytes,
    SUM(lob_bytes) lob_bytes,
    SUM(lobind_bytes) lobind_bytes
  FROM (
    -- Table segments
    SELECT
      owner,
      segment_name table_name,
      bytes total_bytes,
      bytes tab_bytes,
      0 ind_bytes,
      0 lob_bytes,
      0 lobind_bytes
    FROM dba_segments
    WHERE segment_type IN ('TABLE', 'TABLE PARTITION', 'TABLE SUBPARTITION')
    UNION ALL
    -- Index segments
    SELECT
      i.table_owner owner,
      i.table_name,
      s.bytes total_bytes,
      0 tab_bytes,
      s.bytes ind_bytes,
      0 lob_bytes,
      0 lobind_bytes
    FROM dba_indexes i, dba_segments s
    WHERE s.segment_name = i.index_name
    AND s.owner = i.owner
    AND s.segment_type IN ('INDEX', 'INDEX PARTITION', 'INDEX SUBPARTITION')
    UNION ALL
    -- LOB segments
    SELECT
      l.owner,
      l.table_name,
      s.bytes total_bytes,
      0 tab_bytes,
      0 ind_bytes,
      s.bytes lob_bytes,
      0 lobind_bytes
    FROM dba_lobs l, dba_segments s
    WHERE s.segment_name = l.segment_name
    AND s.owner = l.owner
    AND s.segment_type IN ('LOBSEGMENT', 'LOB PARTITION')
    UNION ALL
    -- LOB index segments
    SELECT
      l.owner,
      l.table_name,
      s.bytes total_bytes,
      0 tab_bytes,
      0 ind_bytes,
      0 lob_bytes,
      s.bytes lobind_bytes
    FROM dba_lobs l, dba_segments s
    WHERE s.segment_name = l.index_name
    AND s.owner = l.owner
    AND s.segment_type = 'LOBINDEX'
  )
  GROUP BY owner, table_name
)
SELECT
  t.owner,
  t.table_name,
  ROUND(t.total_bytes / (1024 * 1024), 2) AS Total_MB,
  ROUND(t.tab_bytes / (1024 * 1024), 2) AS Table_MB,
  ROUND(t.ind_bytes / (1024 * 1024), 2) AS Indexes_MB,
  ROUND(t.lob_bytes / (1024 * 1024), 2) AS LOB_MB,
  ROUND(t.lobind_bytes / (1024 * 1024), 2) AS LOBIndexes_MB
FROM tab_size t
ORDER BY t.total_bytes DESC;

SQL

WITH tab_size AS (
  SELECT
    owner,
    table_name,
    SUM(total_bytes) total_bytes,
    SUM(tab_bytes) tab_bytes,
    SUM(ind_bytes) ind_bytes,
    SUM(lob_bytes) lob_bytes,
    SUM(lobind_bytes) lobind_bytes
  FROM (
    -- Table segments
    SELECT
      owner,
      segment_name table_name,
      bytes total_bytes,
      bytes tab_bytes,
      0 ind_bytes,
      0 lob_bytes,
      0 lobind_bytes
    FROM dba_segments
    WHERE segment_type IN ('TABLE', 'TABLE PARTITION', 'TABLE SUBPARTITION')
    UNION ALL
    -- Index segments
    SELECT
      i.table_owner owner,
      i.table_name,
      s.bytes total_bytes,
      0 tab_bytes,
      s.bytes ind_bytes,
      0 lob_bytes,
      0 lobind_bytes
    FROM dba_indexes i, dba_segments s
    WHERE s.segment_name = i.index_name
    AND s.owner = i.owner
    AND s.segment_type IN ('INDEX', 'INDEX PARTITION', 'INDEX SUBPARTITION')
    UNION ALL
    -- LOB segments
    SELECT
      l.owner,
      l.table_name,
      s.bytes total_bytes,
      0 tab_bytes,
      0 ind_bytes,
      s.bytes lob_bytes,
      0 lobind_bytes
    FROM dba_lobs l, dba_segments s
    WHERE s.segment_name = l.segment_name
    AND s.owner = l.owner
    AND s.segment_type IN ('LOBSEGMENT', 'LOB PARTITION')
    UNION ALL
    -- LOB index segments
    SELECT
      l.owner,
      l.table_name,
      s.bytes total_bytes,
      0 tab_bytes,
      0 ind_bytes,
      0 lob_bytes,
      s.bytes lobind_bytes
    FROM dba_lobs l, dba_segments s
    WHERE s.segment_name = l.index_name
    AND s.owner = l.owner
    AND s.segment_type = 'LOBINDEX'
  )
  GROUP BY owner, table_name
)
SELECT
  t.owner,
  t.table_name,
  ROUND(t.total_bytes / (1024 * 1024 * 1024), 2) AS Total_GB,
  ROUND(t.tab_bytes / (1024 * 1024 * 1024), 2) AS Table_GB,
  ROUND(t.ind_bytes / (1024 * 1024 * 1024), 2) AS Indexes_GB,
  ROUND(t.lob_bytes / (1024 * 1024 * 1024), 2) AS LOB_GB,
  ROUND(t.lobind_bytes / (1024 * 1024 * 1024), 2) AS LOBIndexes_GB
FROM tab_size t
ORDER BY t.total_bytes DESC;

Why this query is so powerful for EBS:

  • It aggregates the size of a table and all its related indexes and LOB segments into a single, easy-to-read row.

  • You can see the breakdown of space usage (e.g., "This table is large because of its indexes, not the table data itself").

  • This helps you identify which schemas (e.g., APPLSYS, AP, GL) are growing the most.

Note: To run these queries, you must have the necessary privileges, typically as a DBA or a user with permissions to access the DBA_ views.


Conclusion and Next Steps

By regularly running these queries, you can stay on top of your Oracle EBS database growth. Pinpointing the largest objects is the first step toward effective database management. Once you've identified the culprits, you can investigate potential actions like:

  • Archiving old data: Many large tables contain historical data that can be moved to an archive tablespace or a separate database.

  • Purging data: Some tables, especially log or temporary tables, can have their data purged after a certain period.

  • Analyzing indexes: For large indexes, you might need to analyze them for fragmentation and consider rebuilding or reorganizing them.

  • Compressing tables/indexes: In some cases, Oracle's compression features can significantly reduce space usage.

Proactive monitoring and management of your database's largest objects will ensure your Oracle EBS system remains performant and stable for the long term.

No comments:

Post a Comment