Opening a Physical Standby Database
1. Real-time Query
What is Real-time Query?
Real-time Query allows you to run read-only queries on a physical standby database while redo apply is running in the background.
This means your standby can serve reporting and analytics workloads in real-time, offloading the primary database and maximizing resource usage.
🏷️ This feature is available only with Oracle Active Data Guard (licensed).
Why Use Real-time Query?
Benefit | Explanation |
---|---|
✅ Reporting on standby | Run reports without affecting primary DB |
✅ Real-time data access | Queries see changes as redo is applied |
✅ High availability | Offload workload and still be disaster-ready |
✅ RAC support | Can use Oracle RAC on the standby too |
Requirements Before You Start
Requirement | Detail |
---|---|
Oracle Edition | Enterprise Edition with Active Data Guard license |
Compatible Parameter | Must be 11.0.0 or higher |
Role | Physical standby only (not logical) |
Redo Transport | SYNC mode recommended for accuracy |
Archive Log | Database must be in ARCHIVELOG mode |
Steps to Enable Real-time Query
Here’s how you can enable real-time query on a physical standby:
Step-by-step Guide
-- 1. Cancel managed recovery (stop redo apply)
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
-- 2. Open standby database in read-only mode
ALTER DATABASE OPEN;
-- 3. Restart redo apply in background (real-time apply)
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT;
💡 Now your standby is open for read-only access and applying redo at the same time — this is called “Real-time Query mode”.
How to Check if It’s Working
SELECT open_mode FROM V$DATABASE;
Expected Result:
OPEN_MODE | Meaning |
---|---|
READ ONLY WITH APPLY | Standby is open and applying redo |
READ ONLY | Open, but not applying redo |
MOUNTED | Not open for queries |
Monitor Apply Lag (How behind is the standby?)
SELECT name, value, datum_time, time_computed
FROM V$DATAGUARD_STATS
WHERE name = 'apply lag';
This tells you how much delay exists between the primary and standby.
Control Query Freshness with STANDBY_MAX_DATA_DELAY
By default, Oracle lets you query even if the standby is slightly behind. But you can control how “fresh” the data must be.
Value | Effect |
---|---|
NONE (default) | No delay check — show whatever is there |
0 | Query only if standby is 100% up-to-date |
n (in seconds) | Allow queries if lag is under n seconds |
🔧 Example:
ALTER SESSION SET STANDBY_MAX_DATA_DELAY = 3;
This tells Oracle: “Let me run the query only if the data is at most 3 seconds old.”
⚠️ If not satisfied, Oracle throws:
ORA-03172: standby data not consistent
Want to Wait Until Standby Catches Up?
You can force the session to wait until standby is caught up:
ALTER SESSION SYNC WITH PRIMARY;
This is useful if you’re okay to wait a bit and want guaranteed consistency.
You can also automate this with a trigger, like so:
CREATE TRIGGER adg_logon_sync_trigger
AFTER LOGON ON SCHEMA
BEGIN
IF SYS_CONTEXT('USERENV','DATABASE_ROLE') = 'PHYSICAL STANDBY' THEN
EXECUTE IMMEDIATE 'ALTER SESSION SYNC WITH PRIMARY';
END IF;
END;
What if Data Block is Corrupted?
Real-time query supports automatic block media recovery. If a block is corrupted, Oracle fetches a good copy from the primary automatically.
Manual Recovery (if needed):
RECOVER BLOCK FOR FILE 5 BLOCK 1234;
Real-time Query: Important Notes
Note | Description |
---|---|
Real-time apply must be running | Otherwise queries won’t see latest data |
SYNC is better | For best accuracy and consistency |
Only physical standby supported | Logical standby doesn’t support real-time apply |
Requires Active Data Guard | Needs additional license |
✅ Summary
Feature | Real-time Query |
---|---|
Allows read-only queries on standby | ✅ Yes |
Redo Apply continues in background | ✅ Yes |
Data freshness control | ✅ With STANDBY_MAX_DATA_DELAY |
Auto block repair | ✅ Yes |
Licensing required | ✅ Active Data Guard |
2. Using SQL and PL/SQL on Active Data Guard Standbys
What’s New in 19c?
Starting with Oracle 19c, Active Data Guard now allows SQL and PL/SQL operations on physical standby databases — including DML and top-level PL/SQL blocks.
This means you can now:
- Perform occasional inserts, updates, and deletes
- Run PL/SQL procedures/functions
- Automatically recompile invalid PL/SQL objects
⚠️ But remember — these operations are redirected to the primary, not executed on the standby itself.
🔍 Why Allow DML & PL/SQL on a Standby?
Advantage | Description |
---|---|
✅ Read-mostly apps supported | Ideal for apps that mostly read but occasionally write |
✅ Query + small write support | You don’t need to switch over to primary |
✅ Simplifies development | Developers can work on the standby with fewer restrictions |
✅ Automatic redirection | Oracle forwards changes to the primary for you |
DML Operations on Active Data Guard Standby
How Does It Work?
- DML (e.g.
INSERT
,UPDATE
,DELETE
) is automatically forwarded to the primary database - The standby waits for the change to be applied
- Read consistency is maintained (you can see your own uncommitted changes)
This is useful for interactive dashboards, minor edits, or mixed workloads.
Setup: Enable DML Redirection
Level | Method |
---|---|
System-level (global) | ALTER SYSTEM SET ADG_REDIRECT_DML = TRUE; (requires restart) |
Session-level (preferred for testing) | ALTER SESSION ENABLE ADG_REDIRECT_DML; |
Example
-- On the standby
ALTER SESSION ENABLE ADG_REDIRECT_DML;
-- Run a DML
INSERT INTO employees VALUES (201, 'John', 'Doe', 5000);
✅ This DML is sent to primary, executed there, and the result is shipped back.
Until committed on the primary, only this session sees the change. Other sessions on standby will see it after commit.
DML: Best Practices & Warnings
Point | Detail |
---|---|
❌ Avoid heavy DMLs | Too many writes on standby = overhead on primary |
🚫 No XA transactions | Distributed transactions (XA) are not supported |
🔄 Use session-level config for safety | Avoid making it default unless needed |
✅ Great for small, low-impact writes | Think: logging, bookmarks, temp notes, etc. |
PL/SQL Execution on Standby
You can now run top-level PL/SQL blocks (procedures/functions) on Active Data Guard standby.
These too are automatically redirected to the primary.
💡 “Top-level” means: directly run blocks — not anonymous PL/SQL inside SQL tools.
Enabling PL/SQL Redirection
ALTER SESSION ENABLE ADG_REDIRECT_PLSQL;
🔹 Only works at the session level
🔹 Only for top-level calls (not dynamic SQL or bind variables)
PL/SQL Example
-- Assume this procedure exists on both primary & standby
CREATE OR REPLACE PROCEDURE update_sal (
emp_id IN NUMBER,
sal IN NUMBER
) AS
BEGIN
UPDATE employees SET salary = sal WHERE employee_id = emp_id;
END;
Use it on the standby:
ALTER SESSION ENABLE ADG_REDIRECT_DML; -- Required if PL/SQL uses DML
ALTER SESSION ENABLE ADG_REDIRECT_PLSQL;
EXEC update_sal(105, 6000);
✅ Oracle will redirect the call to the primary, execute it, and return the result.
Automatic Recompilation of Invalid PL/SQL Objects
If a PL/SQL object becomes invalid (e.g., because of a table change), Oracle can recompile it automatically on the primary — even from the standby.
How It Works
- The PL/SQL is invalid
- You attempt to use it on standby
- Oracle redirects the recompilation to the primary
- When done, it ships back the valid object
Requirement
-- Must be enabled to allow this:
ALTER SYSTEM SET ADG_REDIRECT_DML = TRUE;
Recompilation Example
Suppose the update_sal
procedure becomes invalid due to a table change:
-- Table altered on primary:
ALTER TABLE employees ADD COLUMN department_id NUMBER;
-- On standby
ALTER SESSION ENABLE ADG_REDIRECT_DML;
EXEC update_sal(105, 6000); -- Automatically recompiles on primary, then executes
Oracle detects the invalid PL/SQL, redirects the DDL, recompiles, and then executes your call.
✅ Summary Table
Feature | Supported | Notes |
---|---|---|
DML Redirection | ✅ | Auto-forwards to primary |
PL/SQL Redirection | ✅ | Top-level only, no binds |
Automatic PL/SQL Recompilation | ✅ | Triggered on first use |
XA Transactions | ❌ | Not supported |
Mass Writes | 🚫 Not Recommended | Use for small, occasional writes |
Licensing | ✔️ Requires Active Data Guard | Oracle EE + license |
3. Using Temporary Tables on Active Data Guard Instances
What Are Temporary Tables?
Temporary tables are special tables used to hold session-specific or transaction-specific data. Data in these tables is:
- Private to your session
- Automatically deleted after a session or transaction ends
- Not written to disk permanently
- Perfect for reporting, intermediate calculations, or scratch work
🔄 Types of Temporary Tables
Type | Description | Lifetime | Where Stored |
---|---|---|---|
Global Temporary Tables (GTTs) | Metadata is stored in the data dictionary; rows are session- or transaction-specific | Session or transaction | Disk + memory |
Private Temporary Tables (PTTs) | Metadata & data stored in memory only | Session | Memory only |
✅ Can We Use These on Active Data Guard (ADG)?
Yes! Starting with Oracle 12c and enhanced in 19c+, you can create and use:
Table Type | Supported on ADG? | Notes |
---|---|---|
Global Temporary Tables | ✅ | Full DML & DDL supported |
Private Temporary Tables | ✅ | Metadata stored in memory; safe on read-only standby |
Global Temporary Tables (GTT) on ADG
DML on GTT: How It Works
Even though ADG is read-only, Oracle allows DML on GTTs because it uses a feature called Temporary Undo.
📌 Key Concept: Temporary Undo
Feature | Description |
---|---|
What is it? | Stores undo for temporary tables in the temp tablespace, not undo tablespace |
Why allowed? | Doesn’t generate redo → safe on standby |
Where is it always enabled? | Always ON in ADG standby |
How to enable on Primary? | Set TEMP_UNDO_ENABLED = TRUE |
✅ This reduces redo traffic and improves performance for both primary and standby.
Example: DML on Global Temporary Table
-- On the ADG standby
CREATE GLOBAL TEMPORARY TABLE temp_sales (
id NUMBER,
amount NUMBER
) ON COMMIT PRESERVE ROWS;
-- Insert data (allowed!)
INSERT INTO temp_sales VALUES (1, 1000);
✅ Works perfectly! Data is session-specific and no redo is generated.
Benefits of Temporary Undo on ADG
Benefit | Description |
---|---|
✅ Less redo on primary | Because temporary undo isn’t logged in redo |
✅ Less network usage | Less redo to ship to standby |
✅ Supports reporting apps | Useful for BI tools or temporary staging logic |
✅ Fast scratch space | Without permanent writes to disk |
Restrictions on GTT in ADG
Limitation | Explanation |
---|---|
🔒 COMPATIBLE >= 12.0.0 required | For temporary undo feature |
🚫 No temp BLOBs/CLOBs | Unsupported |
🚫 No distributed transactions with GTT | Can’t modify GTT and remote DB in same transaction |
⚠️ EXPLAIN PLAN uses GTT internally | May conflict with remote DML in same session |
❌ TEMP_UNDO_ENABLED has no effect on standby | It’s always ON automatically |
DDL on GTTs: Create/Drop
You can issue CREATE and DROP GTT statements from the ADG standby.
These are redirected to the primary, executed there, and reflected back.
🔁 Managed recovery must be in real-time apply mode and standby must be in sync.
Example: Create GTT on ADG
-- On standby, create table
CREATE GLOBAL TEMPORARY TABLE temp_orders (
order_id NUMBER,
region VARCHAR2(20)
) ON COMMIT PRESERVE ROWS;
✅ Oracle transparently redirects this DDL to the primary, executes it, and reflects the change to the standby.
🔒 Note on DDL Redirection
Condition | Requirement |
---|---|
🟢 Standby apply must be running | With real-time apply enabled |
🟢 Standby must be synced with primary | No large lag |
🛠️ Still can do DDL from primary | ADG standby sees it when caught up |
Private Temporary Tables (PTT) on ADG
What Makes PTTs Special?
Feature | Description |
---|---|
✅ Fully in-memory | No disk metadata → OK on read-only DB |
🔒 Session-bound | Auto-dropped when session ends |
🔧 Lightweight | Ideal for quick calculations or filtering |
🆕 Introduced in | Oracle 18c |
Example: Create PTT on ADG
-- On ADG standby
CREATE PRIVATE TEMPORARY TABLE ora$ptt_sales (
product_id NUMBER,
amount NUMBER
);
✅ No redo, no disk writes — safe and fast on ADG.
❗Table names must start with
ORA$PTT_
orORA$
by default
Quick Feature Summary Table
Feature | GTT | PTT |
---|---|---|
Allowed on ADG? | ✅ Yes | ✅ Yes |
Undo generates redo? | ❌ No (stored in temp tablespace) | ❌ No (in-memory) |
Metadata stored? | ✅ On disk | ❌ In memory only |
Supports DML? | ✅ Yes | ✅ Yes |
Auto dropped? | ❌ No (must drop manually) | ✅ Yes (end of session) |
Requires TEMP_UNDO_ENABLED? | ✅ (on primary) | ❌ Not needed |
📌Summary: Best Practices
Task | Recommendation |
---|---|
Use GTTs for heavy reporting apps | ✅ Ideal for session temp staging |
Prefer PTTs for one-off analytics or filters | ✅ Very fast & in-memory |
Always keep standby in sync | ✅ Required for DDL redirection |
Avoid BLOB/CLOB in GTTs | ❌ Not supported |
Avoid distributed transactions + GTT | ⚠️ Causes errors |
Use real-time apply mode | ✅ Required for DDL visibility on standby |
4. IM Column Store in an Active Data Guard Environment
What Is the IM Column Store?
The In-Memory Column Store (IM column store) is a feature that stores table data in a compressed columnar format in memory, enabling super-fast analytical queries and reporting by scanning only the relevant columns.
Starting with Oracle 12c Release 2 (12.2.0.1), Oracle supports the IM column store on Active Data Guard (ADG) standby databases.
Why Use IM Column Store on ADG?
Using the IM column store on a standby database has several key benefits:
Benefit | Description |
---|---|
🔄 Offload Analytics | Run reporting workloads directly on the standby, reducing load on the primary |
⚡ Faster Query Performance | Columnar format allows fast scans, filters, and aggregations |
📦 Double Memory Utilization | You can populate different data sets in the primary and standby IM stores, effectively doubling IM memory usage across both |
💾 Reduced I/O | Since data is in memory, disk access is minimized |
Configuration Steps
Step | Description |
---|---|
1️⃣ Ensure version is 12.2.0.1 or above | IM support on ADG begins from this version |
2️⃣ Configure memory for IM column store | Use INMEMORY_SIZE parameter on both primary and standby |
3️⃣ On standby, set parameter for MIRA support | ENABLE_IMC_WITH_MIRA = TRUE if using multi-instance redo apply (RAC) |
Example Configuration (Simplified)
-- On standby database
ALTER SYSTEM SET INMEMORY_SIZE = 2G SCOPE=SPFILE;
ALTER SYSTEM SET ENABLE_IMC_WITH_MIRA = TRUE SCOPE=BOTH;
-- Restart the standby instance to activate IM column store
Practical Benefits in an ADG Setup
Scenario | Value |
---|---|
🧾 Heavy BI reporting on standby | Leverages in-memory scanning speed |
📊 Different IM population on standby | Run standby-specific analytics |
🧠 Free up primary memory | Offload less-used datasets to standby’s IM store |
🧪 Test new in-memory strategies | Use standby as a low-risk experimentation ground |
Limitations to Be Aware Of
Limitation | Description |
---|---|
🚫 In-Memory Expressions | Only learned from queries run on primary |
🚫 In-Memory ILM policies | Triggered only by primary activity |
🚫 In-Memory FastStart | ❌ Not supported on standby |
🚫 In-Memory Join Groups | ❌ Not supported on standby |
🔍 Summary Table
Feature | Supported on ADG Standby? | Notes |
---|---|---|
IM Column Store | ✅ Yes | From Oracle 12.2 onwards |
Different IM contents per DB | ✅ Yes | Great for load balancing |
In-Memory Expressions | ❌ No | Only primary learns expressions |
ILM policies | ❌ No | Only primary tracks access |
In-Memory FastStart | ❌ No | Not supported |
In-Memory Join Groups | ❌ No | Not supported |
MIRA (Multi-Instance Redo Apply) support | ✅ Yes | Set ENABLE_IMC_WITH_MIRA = TRUE |
✅ Best Practices
Task | Recommendation |
---|---|
Enable IM column store on standby | ✅ For high-speed analytics |
Use different IM contents | ✅ To maximize memory usage |
Monitor ADG lag | ✅ To ensure real-time reporting accuracy |
Avoid relying on ILM or Join Groups | ❌ These are not supported on standby |
Use for read-mostly, reporting, and BI | ✅ Ideal workload on ADG standby |
5. In-Memory External Tables in an Active Data Guard Environment
What Are In-Memory External Tables?
In-Memory External Tables combine the speed of Oracle In-Memory (IM) column store with the flexibility of external tables (tables that reference data outside the database—e.g., flat files on disk). They allow high-speed analytics on external data as if it’s part of the database, using in-memory columnar format.
With Active Data Guard, this feature is now available on standby databases as well—great for offloading analytics from primary!
Benefits in ADG Environment
Benefit | Description |
---|---|
🔄 Query Offloading | Run external table queries on standby instead of primary |
⚡ Parallel Load & Query | External data is loaded in parallel into IM column store for fast querying |
🧠 Columnar Analytics | Uses compressed column format for fast filtering, scans, and joins |
💽 Less Disk I/O | Queries are satisfied from memory rather than disk reads |
Key Behavior & Configuration Notes
Feature | Description |
---|---|
✅ Supported in ADG | In-memory external tables can be queried on the standby |
⚙️ Parallel Query | External table segments are loaded in parallel on both primary and standby |
🔁 IM Segment Behavior | Using INMEMORY or NO INMEMORY can release or control IM segment usage on standby |
❌ FOR SERVICE Subclause Not Supported | The FOR SERVICE clause in INMEMORY ... DISTRIBUTE is not supported on primary or standby |
How It Works (High-Level Flow)
Step | Action |
---|---|
1️⃣ | Define an external table and enable INMEMORY |
2️⃣ | External table is loaded into IM column store in parallel |
3️⃣ | Queries on standby use this in-memory external data, accelerating performance |
4️⃣ | You can manage memory use with NO INMEMORY or similar directives |
✅ Example Syntax (Simplified)
CREATE TABLE ext_sales (
sale_id NUMBER,
sale_date DATE,
amount NUMBER
)
ORGANIZATION EXTERNAL
(
TYPE ORACLE_LOADER
DEFAULT DIRECTORY ext_data_dir
ACCESS PARAMETERS (
RECORDS DELIMITED BY NEWLINE
FIELDS TERMINATED BY ','
MISSING FIELD VALUES ARE NULL
(
sale_id, sale_date DATE "YYYY-MM-DD", amount
)
)
LOCATION ('sales_data.csv')
)
INMEMORY;
This will load sales_data.csv
into IM column store, and the same table can be queried on the standby database with excellent performance.
Important Limitations
Limitation | Description |
---|---|
❌ FOR SERVICE clause not supported | You cannot use FOR SERVICE with INMEMORY ... DISTRIBUTE in primary or standby |
🔁 Segment control | Using NO INMEMORY will unload the IM external table segment from memory |
🗃️ External table limitations still apply | Read-only, limited DML, metadata must be accessible to standby if needed |
Summary Table
Feature | Supported on Standby? | Notes |
---|---|---|
In-Memory External Tables | ✅ Yes | Loaded and queried in parallel |
Parallel Query | ✅ Yes | Fully supported |
INMEMORY clause | ✅ Yes | Supported with normal usage |
NO INMEMORY clause | ✅ Yes | Unloads segment from memory |
FOR SERVICE clause | ❌ No | Not supported on either primary or standby |
Best Practices
Task | Recommendation |
---|---|
Use IM external tables for reporting | ✅ Offload heavy file-based analytics to standby |
Manage memory with NO INMEMORY when needed | ✅ Helps control memory usage on standby |
Avoid FOR SERVICE clause | ❌ Not supported in ADG setup |
Use parallel queries on standby | ✅ Takes full advantage of IM performance |
Ensure external files are accessible if needed | ✅ Especially if standby needs to reference them directly |
6. Using Sequences in Oracle Active Data Guard
Oracle Active Data Guard supports global sequences (created with default CACHE
and NOORDER
) and session sequences. These sequences can be safely accessed on standby databases with proper caching and setup. This allows read-mostly standby databases to perform limited inserts or operations requiring unique IDs.
1️⃣ Global Sequences on Standby
How They Work
- When a standby database accesses a global sequence for the first time, it requests a range of sequence numbers from the primary.
- The primary database allocates a non-overlapping range based on the CACHE size, and updates the dictionary.
- Standby consumes the assigned range. Once exhausted, it requests a new one.
- Ensures unique values across all standbys and the primary.
💡 Supported only for sequences with
CACHE
andNOORDER
.
Best Practices
- ❗ Always specify
CACHE
with a high enough value to minimize frequent round-trips to the primary. - ❗
ORDER
orNOCACHE
sequences are not supported on standby. - ✅ Define
LOG_ARCHIVE_DEST_n
on terminal standby pointing back to the primary (needed for redo transport for metadata changes).
Example: Multi-Standby Environment
Step 1: On Primary
CREATE GLOBAL TEMPORARY TABLE gtt (a INT);
CREATE SEQUENCE g CACHE 10;
Step 2: On Standby 1
INSERT INTO gtt VALUES (g.NEXTVAL);
-- 1
INSERT INTO gtt VALUES (g.NEXTVAL);
-- 2
SELECT * FROM gtt;
-- A = 1, 2 (standby 1 gets sequence 1–10)
Step 3: On Primary
SELECT g.NEXTVAL FROM dual;
-- 11
SELECT g.NEXTVAL FROM dual;
-- 12 (primary gets 11–20)
Step 4: On Standby 2
INSERT INTO gtt VALUES (g.NEXTVAL);
-- 21
INSERT INTO gtt VALUES (g.NEXTVAL);
-- 22
SELECT * FROM gtt;
-- A = 21, 22 (standby 2 gets 21–30)
2️⃣ Session Sequences on Standby
What Are Session Sequences?
- Special type of sequence: values are unique only within a session, not across sessions.
- Not persistent across sessions.
- Created on primary but can be accessed from read-only or read/write databases (including standby).
- Useful with global temporary tables having session-level visibility.
- Ignores
CACHE
/NOCACHE
andORDER
/NOORDER
.
Creating & Altering Session Sequences
✅ Create a session sequence:
CREATE SEQUENCE s SESSION;
Convert global to session:
ALTER SEQUENCE s SESSION;
Convert session to global:
ALTER SEQUENCE s GLOBAL;
Example: Using Session Sequences
On Primary
CREATE GLOBAL TEMPORARY TABLE gtt (a INT);
CREATE SEQUENCE s SESSION;
On Standby – Session 1
INSERT INTO gtt VALUES (s.NEXTVAL);
-- 1
INSERT INTO gtt VALUES (s.NEXTVAL);
-- 2
SELECT * FROM gtt;
-- A = 1, 2
On Standby – Session 2
INSERT INTO gtt VALUES (s.NEXTVAL);
-- 1
INSERT INTO gtt VALUES (s.NEXTVAL);
-- 2
SELECT * FROM gtt;
-- A = 1, 2 (values are local to this session)
Result: Each session gets its own private range starting from 1.
Notes & Restrictions
Aspect | Global Sequence | Session Sequence |
---|---|---|
Accessible on standby | ✅ Yes | ✅ Yes |
Unique across system | ✅ Yes | ❌ Only within session |
Persistence | ✅ Yes | ❌ Session only |
Supports CACHE/ORDER | ✅ Yes | ❌ Ignored |
Defined on primary | ✅ Yes | ✅ Yes |
Summary
- Use global sequences with
CACHE
(notNOCACHE
) for consistent values across all databases. - Use session sequences for lightweight, session-specific ID generation with temp tables.
- Be aware of round-trips from standby to primary when cache is exhausted.
- Monitor cache size and redo transport when using sequences on standby.
7. Using the Result Cache on Physical Standby Databases
In an Active Data Guard environment, query result caching can be enabled on physical standby databases to improve performance for repeated queries. This reduces computation time for queries that repeatedly access the same data, without impacting the performance of the standby.
Default Behavior
- By default, query results are not cached on a physical standby database.
- Enabling result caching must be done explicitly for each table involved in recurring queries.
How It Works
- Oracle allows the result cache to store query results for enabled tables on physical standby databases.
- A query result will be cached only if all dependent tables used in the query are enabled for result cache using the clause: sqlCopyEdit
RESULT_CACHE (STANDBY ENABLE)
🔸 Views are not cached, even if their underlying tables are enabled.
📌 When Is Result Cache Used?
A query will utilize the standby result cache only if:
- It’s run on a physical standby in Active Data Guard mode.
- All the tables involved in the query are enabled for result cache.
- The query is repeatable (i.e., returns the same result between redo apply intervals).
Enabling Result Cache on Standby Tables
1. Modify Existing Table
To enable result cache for an existing table:
ALTER TABLE employee RESULT_CACHE (STANDBY ENABLE);
2. During Table Creation
To enable result cache while creating the table:
CREATE TABLE employee (
emp_id NUMBER,
ename VARCHAR2(50),
sal NUMBER
) RESULT_CACHE (STANDBY ENABLE);
You may also see this written as:
RESULT_CACHE (STABLE ENABLE);
STABLE
tells Oracle the data does not change frequently and is safe to cache.
💡 Important Notes
Feature / Behavior | Details |
---|---|
Applies to | Tables only |
Views | ❌ Not supported (even if base tables are cached) |
Multi-table queries | ✅ Supported only if all involved tables are result-cache enabled |
PDB Support | ✅ Each PDB in a CDB has its own result cache |
Query Hints | Same syntax and behavior as on the primary |
Other RESULT_CACHE attributes | Work the same on standby as on primary |
🧠 Best Practices
- ✅ Enable result cache for tables used in frequent queries on the standby.
- ❗ Ensure all tables in multi-table queries are enabled for standby cache.
- ❌ Don’t rely on result cache for views or volatile data.
- 🔄 Consider query patterns and use hints (e.g.,
/*+ RESULT_CACHE */
) if needed. - 📊 Monitor cache performance if using it extensively across multiple PDBs.
✅ Summary
- Result caching on standby can significantly boost performance for repetitive read queries.
- You must explicitly enable this feature on each table using the
STANDBY ENABLE
clause. - Only works for tables, not views, and requires Active Data Guard.
- Works per-PDB in container databases.