Skip to content

Oracle to HeliosDB Migration Guide

Oracle to HeliosDB Migration Guide

Version: 1.0 Last Updated: January 2026 Compatibility Target: Oracle 11g, 12c, 18c, 19c, 21c, 23ai


Table of Contents

  1. Introduction
  2. Compatibility Overview
  3. Pre-Migration Assessment
  4. Conceptual Mapping
  5. Step-by-Step Migration
  6. Feature Mapping
  7. PL/SQL Migration
  8. Application Connectivity
  9. Post-Migration Validation
  10. Performance Considerations
  11. Common Issues and Troubleshooting
  12. Rollback Procedures

1. Introduction

1.1 Why Migrate from Oracle to HeliosDB?

Organizations are increasingly migrating from Oracle Database to HeliosDB for several compelling reasons:

Cost Savings

Cost FactorOracleHeliosDBSavings
Processor License (Enterprise)$47,500/coreOpen pricing60-80%
Annual Support22% of licenseIncluded100%
RAC/ClusteringAdditional licenseBuilt-in100%
Partitioning$11,500/coreIncluded100%
Advanced Security$15,000/coreIncluded100%
In-Memory$23,000/coreIncluded100%

Typical 4-year TCO Reduction: 65-85%

Multi-Model Support

HeliosDB provides native support for multiple data models through a single platform:

  • Relational SQL: Full Oracle SQL compatibility
  • Document/JSON: MongoDB-compatible document storage
  • Key-Value: Redis-compatible operations
  • Time-Series: Native time-series optimizations
  • Graph: Cypher query language support
  • Vector: AI/ML embeddings with similarity search

Modern Architecture Advantages

CapabilityOracleHeliosDB
Cloud-NativePartialFull Kubernetes support
Multi-ProtocolNo9+ protocols
Auto-ScalingManual/LicensedAutomatic
Self-HealingManual interventionAI-driven autonomous
ML IntegrationExternal toolsNative in-database ML
HTAPSeparate systemsUnified workload

1.2 Migration Goals

This guide helps you achieve:

  1. Zero data loss during migration
  2. Minimal downtime through parallel operation strategies
  3. Application compatibility with existing Oracle clients
  4. Performance parity or improvement post-migration
  5. Reduced operational complexity through HeliosDB automation

2. Compatibility Overview

2.1 Oracle Protocol Support in HeliosDB

HeliosDB implements the Oracle TNS wire protocol and provides comprehensive Oracle 23ai compatibility:

CategoryCoverageNotes
SQL Language95%+Full Oracle SQL dialect
PL/SQL95%Complete execution engine
DBMS Packages85%Core packages fully implemented
Hierarchical Queries93%Full CONNECT BY support
JSON Functions94%Oracle 21c+ JSON support
Pseudo-columns95%ROWNUM, ROWID, LEVEL
Analytics92%Window functions

2.2 Supported Oracle Features

Fully Supported (Direct Migration)

  • DDL: CREATE TABLE, INDEX, VIEW, MATERIALIZED VIEW, SEQUENCE, SYNONYM
  • DML: SELECT, INSERT, UPDATE, DELETE, MERGE, INSERT ALL
  • Transactions: COMMIT, ROLLBACK, SAVEPOINT, SET TRANSACTION
  • PL/SQL: Procedures, Functions, Packages, Triggers
  • Hierarchical: CONNECT BY, START WITH, LEVEL, SYS_CONNECT_BY_PATH
  • Advanced: PIVOT/UNPIVOT, MERGE, Flashback queries
  • JSON: JSON_VALUE, JSON_QUERY, JSON_TABLE, JSON_OBJECT
  • Analytics: ROW_NUMBER, RANK, DENSE_RANK, LAG, LEAD, LISTAGG

Partially Supported (Requires Modification)

  • MODEL clause (basic support)
  • BFILE data type (read-only)
  • ORA_ROWSCN (partial tracking)
  • Some DBMS_STATS functions

Not Supported (Requires Redesign)

Oracle FeatureHeliosDB Alternative
Oracle RACHeliosDB distributed clustering
Data GuardHeliosDB multi-region replication
Advanced Queuing (AQ)Native streaming + Kafka integration
Spatial (SDO_*)HeliosDB geospatial indexing
Label SecurityRow-level security policies
Oracle TextHeliosDB full-text search

2.3 Connection Compatibility

HeliosDB accepts Oracle client connections via TNS protocol:

Connection Port: 1521 (default)
Protocol: Oracle TNS
Wire Protocol Version: 12.2 compatible

Supported drivers:

  • Oracle JDBC (21c+)
  • cx_Oracle / oracledb (Python)
  • ODP.NET (21c+)
  • oracledb (Node.js 6.x)
  • godror (Go)

3. Pre-Migration Assessment

3.1 Database Inventory

Before migration, perform a comprehensive inventory of your Oracle environment.

Schema Analysis Script

-- Database size summary
SELECT
owner,
segment_type,
COUNT(*) as object_count,
ROUND(SUM(bytes)/1024/1024/1024, 2) as size_gb
FROM dba_segments
WHERE owner NOT IN ('SYS', 'SYSTEM', 'OUTLN', 'DBSNMP')
GROUP BY owner, segment_type
ORDER BY size_gb DESC;
-- Table and index counts per schema
SELECT
owner,
(SELECT COUNT(*) FROM dba_tables WHERE owner = u.username) as tables,
(SELECT COUNT(*) FROM dba_indexes WHERE owner = u.username) as indexes,
(SELECT COUNT(*) FROM dba_views WHERE owner = u.username) as views,
(SELECT COUNT(*) FROM dba_sequences WHERE owner = u.username) as sequences,
(SELECT COUNT(*) FROM dba_procedures WHERE owner = u.username) as procedures
FROM dba_users u
WHERE username NOT IN ('SYS', 'SYSTEM', 'OUTLN')
ORDER BY username;

3.2 PL/SQL Code Analysis

Analyze your PL/SQL codebase for migration complexity:

-- Count PL/SQL objects by type
SELECT
owner,
type,
COUNT(*) as object_count,
SUM(CASE WHEN status = 'VALID' THEN 1 ELSE 0 END) as valid_count,
SUM(CASE WHEN status = 'INVALID' THEN 1 ELSE 0 END) as invalid_count
FROM dba_objects
WHERE object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY',
'TRIGGER', 'TYPE', 'TYPE BODY')
AND owner NOT IN ('SYS', 'SYSTEM')
GROUP BY owner, type
ORDER BY owner, object_count DESC;
-- Count lines of PL/SQL code
SELECT
owner,
type,
SUM(line) as total_lines
FROM dba_source
WHERE owner NOT IN ('SYS', 'SYSTEM')
GROUP BY owner, type
ORDER BY total_lines DESC;

DBMS Package Usage Inventory

Identify which DBMS packages your code uses:

-- Find DBMS package dependencies
SELECT DISTINCT
owner,
name,
referenced_name as dbms_package,
type
FROM dba_dependencies
WHERE referenced_owner = 'SYS'
AND referenced_name LIKE 'DBMS_%'
AND owner NOT IN ('SYS', 'SYSTEM')
ORDER BY referenced_name, owner, name;
-- Common patterns to search for in source code
SELECT owner, name, type, line, text
FROM dba_source
WHERE UPPER(text) LIKE '%DBMS_OUTPUT%'
OR UPPER(text) LIKE '%DBMS_LOB%'
OR UPPER(text) LIKE '%DBMS_SQL%'
OR UPPER(text) LIKE '%DBMS_UTILITY%'
OR UPPER(text) LIKE '%DBMS_SCHEDULER%'
OR UPPER(text) LIKE '%UTL_FILE%'
OR UPPER(text) LIKE '%DBMS_AQ%'
OR UPPER(text) LIKE '%DBMS_XMLGEN%'
ORDER BY owner, name, line;

3.3 Schema Complexity Evaluation

Data Type Inventory

-- Identify data types in use
SELECT
data_type,
COUNT(*) as column_count,
COUNT(DISTINCT owner||'.'||table_name) as table_count
FROM dba_tab_columns
WHERE owner NOT IN ('SYS', 'SYSTEM')
GROUP BY data_type
ORDER BY column_count DESC;

Data Type Migration Risk Assessment:

Risk LevelData Types
Low (Direct)NUMBER, VARCHAR2, DATE, TIMESTAMP, CLOB, BLOB, RAW
Medium (Verify)BFILE, XMLTYPE, INTERVAL, LONG, LONG RAW
High (Convert)SDO_GEOMETRY, ANYDATA, User-defined types

Constraint Analysis

-- Foreign key relationships
SELECT
a.owner,
a.table_name,
COUNT(*) as fk_count
FROM dba_constraints a
WHERE a.constraint_type = 'R'
AND a.owner NOT IN ('SYS', 'SYSTEM')
GROUP BY a.owner, a.table_name
HAVING COUNT(*) > 5
ORDER BY fk_count DESC;
-- Check constraints using Oracle-specific functions
SELECT owner, table_name, constraint_name, search_condition
FROM dba_constraints
WHERE constraint_type = 'C'
AND owner NOT IN ('SYS', 'SYSTEM')
AND (search_condition LIKE '%ROWNUM%'
OR search_condition LIKE '%SYSDATE%'
OR search_condition LIKE '%DECODE%');

3.4 Application Dependencies

Document all applications connecting to Oracle:

-- Active session analysis
SELECT
machine,
program,
module,
COUNT(*) as session_count,
COUNT(DISTINCT username) as user_count
FROM v$session
WHERE type = 'USER'
GROUP BY machine, program, module
ORDER BY session_count DESC;

3.5 Migration Complexity Score

Calculate your migration complexity:

FactorPointsYour Score
Tables < 501
Tables 50-2002
Tables > 2003
PL/SQL LOC < 10K1
PL/SQL LOC 10K-100K2
PL/SQL LOC > 100K3
No DBMS_AQ usage0
Uses DBMS_AQ2
No Oracle RAC0
Uses Oracle RAC2
No Spatial data0
Uses SDO_GEOMETRY3

Total Score Interpretation:

  • 1-4: Simple migration (1-2 weeks)
  • 5-8: Medium complexity (2-6 weeks)
  • 9+: Complex migration (6+ weeks)

4. Conceptual Mapping

4.1 Oracle to HeliosDB Object Mapping

Oracle ConceptHeliosDB EquivalentNotes
DatabaseDatabase1:1 mapping
TablespaceStorage PoolDifferent internal management
SchemaSchemaDirect mapping
TableTableFull compatibility
IndexIndexB-tree, Bitmap supported
SequenceSequenceCompatible syntax
SynonymSynonymPublic/Private supported
ViewViewFull SQL support
Materialized ViewMaterialized ViewRefresh options supported
PackagePackageFull PL/SQL package support
ProcedureProcedureDirect mapping
FunctionFunctionDirect mapping
TriggerTriggerAll trigger types
DBLinkForeign Data WrapperDifferent implementation
DirectoryStorage MountFile system access

4.2 Tablespace to Storage Pool Mapping

Oracle tablespaces map to HeliosDB storage pools with different characteristics:

-- Oracle tablespace query
SELECT tablespace_name, status, contents, extent_management
FROM dba_tablespaces;

HeliosDB Storage Pool Configuration:

-- Create storage pool (HeliosDB)
CREATE STORAGE POOL sales_pool
WITH REPLICATION_FACTOR = 3
COMPRESSION = 'lz4'
ENCRYPTION = 'aes256';
-- Assign table to pool
CREATE TABLE sales.orders (
order_id NUMBER PRIMARY KEY,
order_date DATE
) STORAGE POOL sales_pool;

Mapping Recommendations:

Oracle Tablespace TypeHeliosDB Storage Pool
SYSTEM/SYSAUXsystem_pool (auto-managed)
UNDONot needed (MVCC internal)
TEMPAutomatic temp management
User dataCustom storage pools
Index tablespaceSame pool as data (optional)

4.3 User and Role Mapping

-- Oracle: Create user
CREATE USER app_user IDENTIFIED BY password
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp
QUOTA UNLIMITED ON users;
-- HeliosDB: Create user
CREATE USER app_user WITH PASSWORD 'password'
DEFAULT SCHEMA app_user;
-- Oracle: Grant roles
GRANT CONNECT, RESOURCE TO app_user;
GRANT SELECT ON sales.orders TO app_user;
-- HeliosDB: Grant roles (compatible syntax)
GRANT CONNECT, RESOURCE TO app_user;
GRANT SELECT ON sales.orders TO app_user;

4.4 Sequence Migration

-- Oracle sequence
CREATE SEQUENCE order_seq
START WITH 1000
INCREMENT BY 1
MAXVALUE 999999999
CACHE 100
CYCLE;
-- HeliosDB sequence (compatible syntax)
CREATE SEQUENCE order_seq
START WITH 1000
INCREMENT BY 1
MAXVALUE 999999999
CACHE 100
CYCLE;
-- Usage is identical
SELECT order_seq.NEXTVAL FROM DUAL;
INSERT INTO orders (id) VALUES (order_seq.NEXTVAL);

4.5 Synonym Migration

-- Oracle public synonym
CREATE PUBLIC SYNONYM emp FOR hr.employees;
-- HeliosDB (same syntax)
CREATE PUBLIC SYNONYM emp FOR hr.employees;
-- Private synonym
CREATE SYNONYM my_emp FOR hr.employees;

5. Step-by-Step Migration

5.1 Phase 1: Schema Export Using Data Pump

Full Schema Export

Terminal window
# Oracle Data Pump export
expdp system/password@ORCL \
SCHEMAS=HR,SALES,INVENTORY \
DIRECTORY=DUMP_DIR \
DUMPFILE=schema_export_%U.dmp \
LOGFILE=schema_export.log \
PARALLEL=4 \
CONTENT=ALL \
COMPRESSION=ALL

Schema-Only Export (for translation)

Terminal window
# Export DDL only
expdp system/password@ORCL \
SCHEMAS=HR \
DIRECTORY=DUMP_DIR \
DUMPFILE=ddl_export.dmp \
LOGFILE=ddl_export.log \
CONTENT=METADATA_ONLY

Generate SQL DDL Scripts

-- Using DBMS_METADATA
SET LONG 1000000
SET LONGCHUNKSIZE 1000000
SET PAGESIZE 0
SET LINESIZE 1000
-- Export all tables in schema
SELECT DBMS_METADATA.GET_DDL('TABLE', table_name, owner)
FROM dba_tables
WHERE owner = 'HR';
-- Export all indexes
SELECT DBMS_METADATA.GET_DDL('INDEX', index_name, owner)
FROM dba_indexes
WHERE owner = 'HR'
AND index_type != 'LOB';
-- Export all procedures/functions
SELECT DBMS_METADATA.GET_DDL('PROCEDURE', object_name, owner)
FROM dba_objects
WHERE owner = 'HR'
AND object_type = 'PROCEDURE';
-- Export all packages
SELECT DBMS_METADATA.GET_DDL('PACKAGE', object_name, owner)
FROM dba_objects
WHERE owner = 'HR'
AND object_type = 'PACKAGE';

5.2 Phase 2: Schema Translation for HeliosDB

Most Oracle DDL works directly in HeliosDB. Common translations needed:

Storage Clause Removal

-- Oracle DDL with storage clauses
CREATE TABLE employees (
employee_id NUMBER(10) NOT NULL,
first_name VARCHAR2(50),
hire_date DATE DEFAULT SYSDATE
)
TABLESPACE users
STORAGE (INITIAL 64K NEXT 64K)
PCTFREE 10 PCTUSED 40;
-- HeliosDB equivalent (remove storage specifics)
CREATE TABLE employees (
employee_id NUMBER(10) NOT NULL,
first_name VARCHAR2(50),
hire_date DATE DEFAULT SYSDATE
);
-- Or with storage pool:
-- ) STORAGE POOL users_pool;

Partitioning Translation

-- Oracle range partitioning
CREATE TABLE sales_history (
sale_id NUMBER,
sale_date DATE,
amount NUMBER
)
PARTITION BY RANGE (sale_date) (
PARTITION p_2023 VALUES LESS THAN (DATE '2024-01-01'),
PARTITION p_2024 VALUES LESS THAN (DATE '2025-01-01'),
PARTITION p_max VALUES LESS THAN (MAXVALUE)
);
-- HeliosDB (compatible syntax)
CREATE TABLE sales_history (
sale_id NUMBER,
sale_date DATE,
amount NUMBER
)
PARTITION BY RANGE (sale_date) (
PARTITION p_2023 VALUES LESS THAN (DATE '2024-01-01'),
PARTITION p_2024 VALUES LESS THAN (DATE '2025-01-01'),
PARTITION p_max VALUES LESS THAN (MAXVALUE)
);

Index Translation

-- Oracle bitmap index
CREATE BITMAP INDEX idx_status ON orders(status);
-- HeliosDB (same syntax)
CREATE BITMAP INDEX idx_status ON orders(status);
-- Oracle function-based index
CREATE INDEX idx_upper_name ON employees(UPPER(last_name));
-- HeliosDB (same syntax)
CREATE INDEX idx_upper_name ON employees(UPPER(last_name));

5.3 Phase 3: Data Migration Strategies

HeliosDB can process Oracle Data Pump files directly:

-- Connect to HeliosDB
sqlplus admin/password@//heliosdb-server:1521/heliosdb
-- Import from Data Pump file
IMPORT DATAPUMP FROM '/path/to/schema_export.dmp'
SCHEMAS = HR, SALES
TRANSFORM = STORAGE:N
PARALLEL = 8;

Strategy B: SQL*Loader Format Migration

Terminal window
# Export data from Oracle using SQL*Loader
sqlldr userid=system/password@ORCL \
control=export.ctl \
data=employees.csv \
log=export.log

Control file (export.ctl):

OPTIONS (SKIP=1)
LOAD DATA
CHARACTERSET UTF8
INFILE 'employees.csv'
INTO TABLE employees
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(
employee_id,
first_name,
last_name,
hire_date DATE "YYYY-MM-DD",
salary
)

Import to HeliosDB:

-- Using COPY command
COPY employees FROM '/path/to/employees.csv'
WITH (FORMAT csv, HEADER true);

Strategy C: Parallel ETL with Batch Processing

For large tables (>100GB), use parallel extraction:

-- Oracle: Extract in chunks
SELECT /*+ PARALLEL(e, 8) */
employee_id, first_name, last_name, hire_date, salary
FROM employees e
WHERE MOD(ROWNUM, 8) = 0; -- Run 8 parallel streams

HeliosDB Batch Insert:

-- Use batch insert for performance
BEGIN BATCH INSERT
INSERT INTO employees VALUES (1, 'John', 'Doe', DATE '2020-01-15', 75000);
INSERT INTO employees VALUES (2, 'Jane', 'Smith', DATE '2020-02-20', 82000);
-- ... more rows
END BATCH;

5.4 Phase 4: PL/SQL Migration

Most PL/SQL code migrates directly. See Section 7 for details.

5.5 Phase 5: Application Cutover

Parallel Running Strategy

Week 1-2: Read-only HeliosDB testing
Week 3: Write to both, read from Oracle
Week 4: Write to both, read from HeliosDB
Week 5: HeliosDB primary, Oracle standby
Week 6: Decommission Oracle reads

Connection String Changes

# Oracle connection
oracle_dsn = "oracle+cx_oracle://user:pass@oracle-host:1521/ORCL"
# HeliosDB connection (same driver works)
helios_dsn = "oracle+cx_oracle://user:pass@heliosdb-host:1521/heliosdb"

6. Feature Mapping

6.1 Oracle SQL Extensions in HeliosDB

DECODE Function

-- Oracle DECODE (fully supported)
SELECT
employee_id,
DECODE(status,
'A', 'Active',
'I', 'Inactive',
'T', 'Terminated',
'Unknown') as status_desc
FROM employees;

NVL and NVL2

-- NVL (replace NULL)
SELECT NVL(commission, 0) FROM employees;
-- NVL2 (if not null / if null)
SELECT NVL2(manager_id, 'Has Manager', 'Top Level') FROM employees;

ROWNUM and ROWID

-- ROWNUM for limiting
SELECT * FROM employees WHERE ROWNUM <= 10;
-- ROWID for row identification
SELECT ROWID, employee_id FROM employees WHERE department_id = 10;

6.2 DBMS Package Mapping

DBMS_OUTPUT

-- Fully supported
BEGIN
DBMS_OUTPUT.ENABLE(1000000);
DBMS_OUTPUT.PUT_LINE('Processing started');
DBMS_OUTPUT.PUT('Status: ');
DBMS_OUTPUT.PUT_LINE('Complete');
DBMS_OUTPUT.NEW_LINE;
END;
/

DBMS_LOB

-- LOB operations (fully supported)
DECLARE
v_clob CLOB;
v_length NUMBER;
BEGIN
SELECT document INTO v_clob FROM documents WHERE id = 1;
v_length := DBMS_LOB.GETLENGTH(v_clob);
DBMS_OUTPUT.PUT_LINE('Length: ' || v_length);
-- Substring
DBMS_OUTPUT.PUT_LINE(DBMS_LOB.SUBSTR(v_clob, 100, 1));
-- Append
DBMS_LOB.APPEND(v_clob, ' Additional text');
END;
/

DBMS_SQL

-- Dynamic SQL (fully supported)
DECLARE
v_cursor INTEGER;
v_rows INTEGER;
BEGIN
v_cursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(v_cursor,
'UPDATE employees SET salary = salary * 1.1 WHERE department_id = :dept',
DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(v_cursor, ':dept', 10);
v_rows := DBMS_SQL.EXECUTE(v_cursor);
DBMS_OUTPUT.PUT_LINE('Updated ' || v_rows || ' rows');
DBMS_SQL.CLOSE_CURSOR(v_cursor);
END;
/

DBMS_SCHEDULER

-- Job scheduling (fully supported)
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'NIGHTLY_CLEANUP',
job_type => 'STORED_PROCEDURE',
job_action => 'cleanup_old_data',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY; BYHOUR=2; BYMINUTE=0',
enabled => TRUE
);
END;
/
-- Manage jobs
BEGIN
DBMS_SCHEDULER.RUN_JOB('NIGHTLY_CLEANUP');
DBMS_SCHEDULER.DISABLE('NIGHTLY_CLEANUP');
DBMS_SCHEDULER.DROP_JOB('NIGHTLY_CLEANUP');
END;
/

DBMS_METADATA

-- Schema export (fully supported)
SELECT DBMS_METADATA.GET_DDL('TABLE', 'EMPLOYEES', 'HR') FROM DUAL;
SELECT DBMS_METADATA.GET_DEPENDENT_DDL('INDEX', 'EMPLOYEES', 'HR') FROM DUAL;

UTL_FILE

-- File I/O (fully supported)
DECLARE
v_file UTL_FILE.FILE_TYPE;
v_line VARCHAR2(32767);
BEGIN
v_file := UTL_FILE.FOPEN('DATA_DIR', 'output.txt', 'W');
UTL_FILE.PUT_LINE(v_file, 'Header line');
FOR rec IN (SELECT * FROM employees) LOOP
UTL_FILE.PUT_LINE(v_file, rec.employee_id || ',' || rec.first_name);
END LOOP;
UTL_FILE.FCLOSE(v_file);
END;
/

6.3 Partitioning Support

-- Range partitioning
CREATE TABLE sales (
sale_id NUMBER,
sale_date DATE
) PARTITION BY RANGE (sale_date) (
PARTITION p_q1 VALUES LESS THAN (DATE '2024-04-01'),
PARTITION p_q2 VALUES LESS THAN (DATE '2024-07-01'),
PARTITION p_q3 VALUES LESS THAN (DATE '2024-10-01'),
PARTITION p_q4 VALUES LESS THAN (DATE '2025-01-01')
);
-- List partitioning
CREATE TABLE orders (
order_id NUMBER,
region VARCHAR2(20)
) PARTITION BY LIST (region) (
PARTITION p_east VALUES ('NY', 'NJ', 'CT'),
PARTITION p_west VALUES ('CA', 'WA', 'OR'),
PARTITION p_other VALUES (DEFAULT)
);
-- Hash partitioning
CREATE TABLE customers (
customer_id NUMBER,
name VARCHAR2(100)
) PARTITION BY HASH (customer_id) PARTITIONS 16;

6.4 Flashback to Time Travel Mapping

Oracle Flashback maps to HeliosDB Time Travel:

-- Oracle Flashback Query
SELECT * FROM employees AS OF TIMESTAMP
TO_TIMESTAMP('2024-01-15 10:00:00', 'YYYY-MM-DD HH24:MI:SS');
-- HeliosDB Time Travel (identical syntax)
SELECT * FROM employees AS OF TIMESTAMP
TO_TIMESTAMP('2024-01-15 10:00:00', 'YYYY-MM-DD HH24:MI:SS');
-- Oracle Flashback with SCN
SELECT * FROM employees AS OF SCN 12345678;
-- HeliosDB (identical syntax)
SELECT * FROM employees AS OF SCN 12345678;
-- Versions between timestamps
SELECT versions_starttime, versions_endtime, versions_operation,
employee_id, salary
FROM employees
VERSIONS BETWEEN TIMESTAMP
TO_TIMESTAMP('2024-01-01', 'YYYY-MM-DD') AND
TO_TIMESTAMP('2024-01-31', 'YYYY-MM-DD')
WHERE employee_id = 100;

HeliosDB Time Travel Advantages:

  • Configurable retention (7+ days default)
  • Delta compression (<10% storage overhead)
  • Sub-millisecond temporal queries
  • Integrated with MVCC

7. PL/SQL Migration

7.1 Supported PL/SQL Constructs

HeliosDB provides 95% PL/SQL compatibility:

Variable Declarations

DECLARE
-- Scalar types
v_number NUMBER(10,2) := 100.50;
v_string VARCHAR2(100) := 'Hello';
v_date DATE := SYSDATE;
v_timestamp TIMESTAMP := SYSTIMESTAMP;
v_boolean BOOLEAN := TRUE;
-- Constants
c_tax_rate CONSTANT NUMBER := 0.08;
-- Anchored types
v_salary employees.salary%TYPE;
v_emp_row employees%ROWTYPE;
-- Collections
TYPE num_array IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
v_numbers num_array;
-- Nested tables
TYPE name_list IS TABLE OF VARCHAR2(100);
v_names name_list := name_list('John', 'Jane', 'Bob');
BEGIN
-- Body
NULL;
END;
/

Control Flow

DECLARE
v_grade CHAR(1);
v_score NUMBER := 85;
BEGIN
-- IF-THEN-ELSE
IF v_score >= 90 THEN
v_grade := 'A';
ELSIF v_score >= 80 THEN
v_grade := 'B';
ELSIF v_score >= 70 THEN
v_grade := 'C';
ELSE
v_grade := 'F';
END IF;
-- CASE expression
v_grade := CASE
WHEN v_score >= 90 THEN 'A'
WHEN v_score >= 80 THEN 'B'
WHEN v_score >= 70 THEN 'C'
ELSE 'F'
END;
-- Simple LOOP
LOOP
v_score := v_score - 10;
EXIT WHEN v_score < 0;
END LOOP;
-- WHILE loop
v_score := 100;
WHILE v_score > 0 LOOP
v_score := v_score - 10;
END LOOP;
-- FOR loop
FOR i IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE('Iteration: ' || i);
END LOOP;
-- FOR loop with REVERSE
FOR i IN REVERSE 1..10 LOOP
DBMS_OUTPUT.PUT_LINE('Countdown: ' || i);
END LOOP;
END;
/

Cursors

DECLARE
-- Explicit cursor
CURSOR emp_cursor IS
SELECT employee_id, first_name, salary
FROM employees
WHERE department_id = 10;
-- Cursor with parameters
CURSOR dept_cursor(p_dept_id NUMBER) IS
SELECT * FROM employees WHERE department_id = p_dept_id;
v_emp emp_cursor%ROWTYPE;
BEGIN
-- Explicit cursor operations
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_emp;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp.first_name);
END LOOP;
CLOSE emp_cursor;
-- Cursor FOR loop (implicit)
FOR rec IN emp_cursor LOOP
DBMS_OUTPUT.PUT_LINE(rec.first_name || ': ' || rec.salary);
END LOOP;
-- Cursor with parameters
FOR rec IN dept_cursor(20) LOOP
DBMS_OUTPUT.PUT_LINE(rec.first_name);
END LOOP;
END;
/

BULK COLLECT and FORALL

DECLARE
TYPE emp_tab IS TABLE OF employees%ROWTYPE;
TYPE id_tab IS TABLE OF NUMBER;
v_employees emp_tab;
v_ids id_tab := id_tab(1, 2, 3, 4, 5);
BEGIN
-- BULK COLLECT
SELECT *
BULK COLLECT INTO v_employees
FROM employees
WHERE department_id = 10;
DBMS_OUTPUT.PUT_LINE('Collected ' || v_employees.COUNT || ' rows');
-- FORALL with SAVE EXCEPTIONS
FORALL i IN v_ids.FIRST..v_ids.LAST SAVE EXCEPTIONS
UPDATE employees
SET salary = salary * 1.1
WHERE employee_id = v_ids(i);
EXCEPTION
WHEN OTHERS THEN
FOR j IN 1..SQL%BULK_EXCEPTIONS.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Error at index ' ||
SQL%BULK_EXCEPTIONS(j).ERROR_INDEX);
END LOOP;
END;
/

7.2 Exception Handling

DECLARE
v_salary NUMBER;
-- Custom exception
e_salary_too_high EXCEPTION;
PRAGMA EXCEPTION_INIT(e_salary_too_high, -20001);
BEGIN
SELECT salary INTO v_salary
FROM employees
WHERE employee_id = 999; -- May not exist
IF v_salary > 1000000 THEN
RAISE e_salary_too_high;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Employee not found');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Multiple employees returned');
WHEN e_salary_too_high THEN
DBMS_OUTPUT.PUT_LINE('Salary exceeds maximum');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error: ' || SQLCODE || ' - ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
RAISE;
END;
/

7.3 Stored Procedures

CREATE OR REPLACE PROCEDURE transfer_funds(
p_from_account IN NUMBER,
p_to_account IN NUMBER,
p_amount IN NUMBER,
p_status OUT VARCHAR2
) AS
v_from_balance NUMBER;
e_insufficient_funds EXCEPTION;
BEGIN
-- Check source balance
SELECT balance INTO v_from_balance
FROM accounts
WHERE account_id = p_from_account
FOR UPDATE;
IF v_from_balance < p_amount THEN
RAISE e_insufficient_funds;
END IF;
-- Perform transfer
UPDATE accounts SET balance = balance - p_amount
WHERE account_id = p_from_account;
UPDATE accounts SET balance = balance + p_amount
WHERE account_id = p_to_account;
COMMIT;
p_status := 'SUCCESS';
EXCEPTION
WHEN e_insufficient_funds THEN
ROLLBACK;
p_status := 'INSUFFICIENT_FUNDS';
WHEN OTHERS THEN
ROLLBACK;
p_status := 'ERROR: ' || SQLERRM;
END transfer_funds;
/

7.4 Packages

-- Package specification
CREATE OR REPLACE PACKAGE employee_pkg AS
-- Types
TYPE emp_rec IS RECORD (
emp_id NUMBER,
emp_name VARCHAR2(100),
salary NUMBER
);
TYPE emp_tab IS TABLE OF emp_rec;
-- Constants
c_max_salary CONSTANT NUMBER := 500000;
-- Procedures
PROCEDURE hire_employee(
p_name IN VARCHAR2,
p_dept_id IN NUMBER,
p_salary IN NUMBER
);
-- Functions
FUNCTION get_employee_count(p_dept_id IN NUMBER) RETURN NUMBER;
FUNCTION get_department_employees(p_dept_id IN NUMBER) RETURN emp_tab PIPELINED;
END employee_pkg;
/
-- Package body
CREATE OR REPLACE PACKAGE BODY employee_pkg AS
PROCEDURE hire_employee(
p_name IN VARCHAR2,
p_dept_id IN NUMBER,
p_salary IN NUMBER
) AS
BEGIN
IF p_salary > c_max_salary THEN
RAISE_APPLICATION_ERROR(-20001, 'Salary exceeds maximum');
END IF;
INSERT INTO employees (employee_id, employee_name, department_id, salary)
VALUES (emp_seq.NEXTVAL, p_name, p_dept_id, p_salary);
COMMIT;
END hire_employee;
FUNCTION get_employee_count(p_dept_id IN NUMBER) RETURN NUMBER AS
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count
FROM employees
WHERE department_id = p_dept_id;
RETURN v_count;
END get_employee_count;
FUNCTION get_department_employees(p_dept_id IN NUMBER)
RETURN emp_tab PIPELINED AS
BEGIN
FOR rec IN (
SELECT employee_id, employee_name, salary
FROM employees
WHERE department_id = p_dept_id
) LOOP
PIPE ROW(emp_rec(rec.employee_id, rec.employee_name, rec.salary));
END LOOP;
RETURN;
END get_department_employees;
END employee_pkg;
/

7.5 Triggers

-- Row-level trigger
CREATE OR REPLACE TRIGGER emp_audit_trigger
AFTER INSERT OR UPDATE OR DELETE ON employees
FOR EACH ROW
DECLARE
v_action VARCHAR2(10);
BEGIN
IF INSERTING THEN
v_action := 'INSERT';
ELSIF UPDATING THEN
v_action := 'UPDATE';
ELSIF DELETING THEN
v_action := 'DELETE';
END IF;
INSERT INTO emp_audit (
audit_id,
employee_id,
action,
action_date,
old_salary,
new_salary,
changed_by
) VALUES (
audit_seq.NEXTVAL,
NVL(:NEW.employee_id, :OLD.employee_id),
v_action,
SYSDATE,
:OLD.salary,
:NEW.salary,
USER
);
END;
/
-- Statement-level trigger
CREATE OR REPLACE TRIGGER dept_stats_trigger
AFTER INSERT OR UPDATE OR DELETE ON employees
DECLARE
BEGIN
-- Update department statistics
MERGE INTO department_stats t
USING (
SELECT department_id, COUNT(*) as emp_count, AVG(salary) as avg_salary
FROM employees
GROUP BY department_id
) s ON (t.department_id = s.department_id)
WHEN MATCHED THEN
UPDATE SET t.emp_count = s.emp_count, t.avg_salary = s.avg_salary
WHEN NOT MATCHED THEN
INSERT (department_id, emp_count, avg_salary)
VALUES (s.department_id, s.emp_count, s.avg_salary);
END;
/
-- INSTEAD OF trigger (for views)
CREATE OR REPLACE TRIGGER emp_view_trigger
INSTEAD OF INSERT ON emp_department_view
FOR EACH ROW
BEGIN
INSERT INTO employees (employee_id, employee_name, department_id)
VALUES (:NEW.employee_id, :NEW.employee_name, :NEW.department_id);
END;
/

7.6 Conversion Patterns for Unsupported Features

DBMS_AQ (Advanced Queuing) to HeliosDB Streaming

-- Oracle AQ
DBMS_AQ.ENQUEUE(
queue_name => 'order_queue',
message_properties => msg_props,
payload => order_message
);
-- HeliosDB: Use streaming table
INSERT INTO order_stream (order_id, order_data, created_at)
VALUES (123, '{"customer": "ABC"}', CURRENT_TIMESTAMP);
-- Consumer reads from stream
SELECT * FROM order_stream
WHERE processed = FALSE
ORDER BY created_at
FOR UPDATE SKIP LOCKED
LIMIT 10;

Oracle Spatial to HeliosDB Geospatial

-- Oracle SDO_GEOMETRY
SELECT * FROM stores
WHERE SDO_WITHIN_DISTANCE(
location,
SDO_GEOMETRY(2001, 4326, SDO_POINT_TYPE(-73.98, 40.75, NULL), NULL, NULL),
'distance=10 unit=km'
) = 'TRUE';
-- HeliosDB geospatial
SELECT * FROM stores
WHERE ST_DWithin(
location,
ST_SetSRID(ST_MakePoint(-73.98, 40.75), 4326),
10000 -- meters
);

8. Application Connectivity

8.1 TNS Configuration

tnsnames.ora for HeliosDB

HELIOSDB =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = heliosdb-server)(PORT = 1521))
(CONNECT_DATA =
(SERVICE_NAME = heliosdb)
)
)
# High availability with multiple hosts
HELIOSDB_HA =
(DESCRIPTION =
(LOAD_BALANCE = ON)
(FAILOVER = ON)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = helios1)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = helios2)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = helios3)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = heliosdb)
)
)

8.2 JDBC Configuration

import java.sql.*;
import oracle.jdbc.pool.OracleDataSource;
public class HeliosDBConnection {
public static void main(String[] args) throws SQLException {
// Simple connection
String url = "jdbc:oracle:thin:@//heliosdb-server:1521/heliosdb";
Connection conn = DriverManager.getConnection(url, "user", "password");
// With connection pool
OracleDataSource ods = new OracleDataSource();
ods.setURL("jdbc:oracle:thin:@//heliosdb-server:1521/heliosdb");
ods.setUser("user");
ods.setPassword("password");
// Pool settings
ods.setConnectionCacheEnabled(true);
ods.setConnectionCacheName("HELIOS_POOL");
Properties cacheProps = new Properties();
cacheProps.setProperty("MinLimit", "5");
cacheProps.setProperty("MaxLimit", "50");
cacheProps.setProperty("InitialLimit", "10");
ods.setConnectionCacheProperties(cacheProps);
Connection pooledConn = ods.getConnection();
}
}

8.3 Python (oracledb) Configuration

import oracledb
# Thin mode (no Oracle Client needed)
oracledb.init_oracle_client() # Optional for thick mode
# Simple connection
connection = oracledb.connect(
user="admin",
password="password",
dsn="heliosdb-server:1521/heliosdb"
)
# Connection pool
pool = oracledb.create_pool(
user="admin",
password="password",
dsn="heliosdb-server:1521/heliosdb",
min=5,
max=50,
increment=5,
threaded=True,
getmode=oracledb.POOL_GETMODE_WAIT
)
# Get connection from pool
with pool.acquire() as connection:
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM employees WHERE department_id = :1", [10])
for row in cursor:
print(row)

8.4 Node.js (oracledb) Configuration

const oracledb = require('oracledb');
// Connection pool
async function initPool() {
await oracledb.createPool({
user: 'admin',
password: 'password',
connectString: 'heliosdb-server:1521/heliosdb',
poolMin: 5,
poolMax: 50,
poolIncrement: 5,
poolTimeout: 60
});
}
// Execute query
async function runQuery() {
let connection;
try {
connection = await oracledb.getConnection();
const result = await connection.execute(
`SELECT employee_id, first_name, salary
FROM employees
WHERE department_id = :deptId`,
{ deptId: 10 },
{ outFormat: oracledb.OUT_FORMAT_OBJECT }
);
console.log(result.rows);
} finally {
if (connection) {
await connection.close();
}
}
}

8.5 .NET (ODP.NET) Configuration

using Oracle.ManagedDataAccess.Client;
// Connection string
string connString = @"
User Id=admin;
Password=password;
Data Source=heliosdb-server:1521/heliosdb;
Pooling=true;
Min Pool Size=5;
Max Pool Size=50;
Connection Timeout=30";
using (OracleConnection conn = new OracleConnection(connString))
{
conn.Open();
using (OracleCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM employees WHERE department_id = :dept";
cmd.Parameters.Add("dept", OracleDbType.Int32).Value = 10;
using (OracleDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine($"{reader["EMPLOYEE_ID"]}: {reader["FIRST_NAME"]}");
}
}
}
}

9. Post-Migration Validation

9.1 Data Integrity Validation

Row Count Verification

-- Generate comparison queries
SELECT
'SELECT ''' || table_name || ''' as table_name, COUNT(*) as row_count FROM ' ||
owner || '.' || table_name || ';' as validation_query
FROM dba_tables
WHERE owner = 'HR'
ORDER BY table_name;
-- Execute on both Oracle and HeliosDB, compare results

Checksum Validation

-- Oracle: Generate row checksums
SELECT
table_name,
ORA_HASH(
LISTAGG(column_value, '|') WITHIN GROUP (ORDER BY column_name)
) as table_checksum
FROM (
SELECT
c.table_name,
c.column_name,
SUM(ORA_HASH(c.column_name)) as column_value
FROM dba_tab_columns c
WHERE c.owner = 'HR'
GROUP BY c.table_name, c.column_name
)
GROUP BY table_name;
-- Compare with HeliosDB
SELECT
table_name,
HASH(STRING_AGG(column_value::text, '|' ORDER BY column_name)) as table_checksum
FROM (...)
GROUP BY table_name;

9.2 Functional Validation

Stored Procedure Testing

-- Create test harness
CREATE TABLE migration_test_results (
test_id NUMBER PRIMARY KEY,
test_name VARCHAR2(200),
test_type VARCHAR2(50),
oracle_result VARCHAR2(4000),
helios_result VARCHAR2(4000),
match_status VARCHAR2(20),
test_date TIMESTAMP DEFAULT SYSTIMESTAMP
);
-- Test procedure execution
DECLARE
v_oracle_result VARCHAR2(4000);
v_helios_result VARCHAR2(4000);
BEGIN
-- Execute on Oracle
v_oracle_result := test_procedure_on_oracle();
-- Execute on HeliosDB
v_helios_result := test_procedure_on_heliosdb();
INSERT INTO migration_test_results (
test_id, test_name, test_type,
oracle_result, helios_result,
match_status
) VALUES (
test_seq.NEXTVAL, 'calculate_salary', 'FUNCTION',
v_oracle_result, v_helios_result,
CASE WHEN v_oracle_result = v_helios_result THEN 'PASS' ELSE 'FAIL' END
);
END;
/

9.3 Performance Validation

Query Performance Comparison

-- Capture Oracle execution times
SET TIMING ON
SET AUTOTRACE ON
SELECT /*+ Oracle baseline */ *
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE d.location_id = 1700;
-- Compare with HeliosDB
EXPLAIN ANALYZE
SELECT *
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE d.location_id = 1700;

9.4 Validation Checklist

CategoryValidation ItemStatus
DataRow counts match[ ]
DataChecksums match[ ]
DataSample data spot checks[ ]
SchemaAll tables created[ ]
SchemaAll indexes created[ ]
SchemaAll constraints active[ ]
SchemaAll sequences created[ ]
PL/SQLProcedures compile[ ]
PL/SQLFunctions return correct values[ ]
PL/SQLPackages compile[ ]
PL/SQLTriggers fire correctly[ ]
SecurityUsers created[ ]
SecurityGrants applied[ ]
PerformanceKey queries perform acceptably[ ]
ApplicationConnection successful[ ]
ApplicationCRUD operations work[ ]
ApplicationTransactions commit/rollback[ ]

10. Performance Considerations

10.1 HeliosDB Performance Features

HeliosDB provides automatic performance optimizations:

FeatureDescriptionBenefit
Auto-IndexingML-based index recommendations30-50% query improvement
Adaptive Query ExecutionRuntime plan optimizationHandles data skew
Global Distributed CacheMulti-tier caching10-100x repeated queries
Query Pattern LearningLearns access patternsProactive optimization
Predicate PushdownFilter pushdown to storage3-10x faster scans

10.2 Index Optimization

-- HeliosDB auto-index recommendation
EXPLAIN ANALYZE SELECT * FROM orders
WHERE customer_id = 123 AND order_date > DATE '2024-01-01';
-- Review index recommendations
SELECT * FROM heliosdb_index_recommendations
WHERE table_name = 'orders';
-- Apply recommended indexes
CREATE INDEX idx_orders_cust_date ON orders(customer_id, order_date);

10.3 Statistics Collection

-- Analyze tables after migration
ANALYZE TABLE employees COMPUTE STATISTICS;
-- For large tables, use sampling
ANALYZE TABLE large_orders ESTIMATE STATISTICS SAMPLE 10 PERCENT;
-- Schedule regular statistics updates
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'NIGHTLY_STATS',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN ANALYZE; END;',
repeat_interval => 'FREQ=DAILY; BYHOUR=3'
);
END;
/

10.4 Query Tuning

-- Enable query hints (Oracle-compatible)
SELECT /*+ INDEX(e idx_emp_dept) */ *
FROM employees e
WHERE department_id = 10;
-- Parallel query execution
SELECT /*+ PARALLEL(orders, 8) */
customer_id, SUM(amount)
FROM orders
GROUP BY customer_id;
-- Use EXPLAIN PLAN
EXPLAIN PLAN FOR
SELECT * FROM employees WHERE department_id = 10;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

10.5 Memory and Resource Tuning

# HeliosDB configuration (heliosdb.toml)
[oracle.memory]
pga_aggregate_target = "4GB"
sort_area_size = 256000
hash_area_size = 512000
[oracle.optimizer]
mode = "ALL_ROWS"
cost_based = true
query_rewrite = true
[cache]
query_result_cache_size = "1GB"
metadata_cache_size = "256MB"

11. Common Issues and Troubleshooting

11.1 Connection Issues

Error: ORA-12154 (TNS Alias Not Found)

Cause: TNS name not in tnsnames.ora or LDAP

Solution:

Terminal window
# Verify tnsnames.ora location
echo $TNS_ADMIN
cat $TNS_ADMIN/tnsnames.ora
# Test with Easy Connect
sqlplus admin/password@//heliosdb-server:1521/heliosdb

Error: ORA-12541 (No Listener)

Cause: HeliosDB Oracle protocol not running

Solution:

Terminal window
# Check HeliosDB Oracle listener status
heliosdb status --protocol oracle
# Verify port is open
netstat -an | grep 1521
telnet heliosdb-server 1521

11.2 SQL Compatibility Issues

Error: Invalid Column Name/Type

Cause: Reserved word or unsupported type

Solution:

-- Quote reserved words
SELECT "LEVEL", "SIZE", "DATE" FROM my_table;
-- Check for unsupported types
SELECT column_name, data_type
FROM user_tab_columns
WHERE data_type IN ('SDO_GEOMETRY', 'ANYDATA', 'BFILE');

Error: PL/SQL Compilation Error

Cause: Unsupported syntax or package

Solution:

-- Show compilation errors
SHOW ERRORS PROCEDURE my_procedure;
-- Check for unsupported packages
SELECT name, text
FROM user_source
WHERE UPPER(text) LIKE '%DBMS_AQ%' -- Not supported
OR UPPER(text) LIKE '%SDO_%'; -- Not supported

11.3 Data Migration Issues

Large Object (LOB) Migration Errors

Cause: LOB size or corruption

Solution:

-- Verify LOB integrity on Oracle
SELECT table_name, column_name, segment_name
FROM dba_lobs
WHERE owner = 'HR';
-- Check for corrupted LOBs
SELECT id, DBMS_LOB.GETLENGTH(document) as lob_length
FROM documents
WHERE DBMS_LOB.GETLENGTH(document) IS NULL;

Character Set Conversion Issues

Cause: Different character sets

Solution:

-- Check Oracle character set
SELECT parameter, value
FROM nls_database_parameters
WHERE parameter IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET');
-- Configure HeliosDB to match
ALTER SESSION SET NLS_CHARACTERSET = 'AL32UTF8';

11.4 Performance Issues

Slow Queries After Migration

Cause: Missing statistics or indexes

Solution:

-- Rebuild statistics
ANALYZE TABLE slow_table COMPUTE STATISTICS;
-- Check for missing indexes
SELECT * FROM heliosdb_index_recommendations
WHERE estimated_improvement > 50;
-- Force index usage if needed
SELECT /*+ INDEX(t idx_name) */ * FROM slow_table t WHERE ...;

High Memory Usage

Cause: Large result sets or inefficient queries

Solution:

-- Use pagination
SELECT * FROM large_table
WHERE ROWNUM <= 1000
OFFSET 0 ROWS;
-- Enable result set streaming
SET ARRAYSIZE 100

11.5 Error Code Mapping

Oracle ErrorHeliosDB ErrorResolution
ORA-00001Unique constraint violationSame handling
ORA-00054Resource busyRetry transaction
ORA-00060Deadlock detectedAuto-resolved, retry
ORA-01403No data foundSame handling
ORA-01422Too many rowsSame handling
ORA-01555Snapshot too oldIncrease retention
ORA-04031Shared pool exhaustedIncrease cache size

12. Rollback Procedures

12.1 Pre-Migration Rollback Preparation

Before starting migration, ensure rollback capability:

-- Create rollback savepoint in Oracle
CREATE RESTORE POINT pre_migration GUARANTEE FLASHBACK DATABASE;
-- Document current Oracle configuration
SELECT name, value FROM v$parameter ORDER BY name;
-- Export application connection strings
-- Document all TNS entries

12.2 During Migration Rollback

If migration fails mid-process:

Terminal window
# Stop HeliosDB data ingestion
heliosdb migration pause --job-id <migration-job>
# Verify Oracle is still primary
sqlplus admin/password@ORACLE_PRIMARY
# Check Oracle Data Guard sync status (if using)
SELECT database_role, open_mode FROM v$database;

12.3 Post-Migration Rollback

If issues are discovered after cutover:

Step 1: Switch Back to Oracle

Terminal window
# Update DNS/Load balancer to point to Oracle
# Update application connection strings
# For applications using TNS
# Edit tnsnames.ora to point back to Oracle
PRODUCTION =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = oracle-server)(PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = ORCL))
)

Step 2: Sync Data Back to Oracle

-- If using parallel write during migration
-- Data should already be in Oracle
-- If not, export from HeliosDB
EXPORT TABLE changed_data TO '/backup/changes.dmp'
WHERE modified_date > TO_DATE('2024-01-15', 'YYYY-MM-DD');
-- Import to Oracle
impdp system/password@ORCL \
DUMPFILE=changes.dmp \
DIRECTORY=DUMP_DIR \
TABLE_EXISTS_ACTION=REPLACE

Step 3: Restore Oracle from Flashback

-- If Oracle Flashback was configured
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
FLASHBACK DATABASE TO RESTORE POINT pre_migration;
ALTER DATABASE OPEN RESETLOGS;

12.4 Rollback Checklist

StepActionStatus
1Stop HeliosDB writes[ ]
2Verify Oracle connectivity[ ]
3Update connection strings[ ]
4Test application connectivity[ ]
5Sync any delta data[ ]
6Validate data integrity[ ]
7Resume Oracle operations[ ]
8Notify stakeholders[ ]

12.5 Rollback Decision Criteria

Consider rollback if:

  • Data integrity issues that cannot be resolved within SLA
  • Performance degradation >50% on critical queries
  • Application functionality failures affecting users
  • Security vulnerabilities discovered
  • Unplanned extended downtime

Do NOT rollback for:

  • Minor performance differences (optimize instead)
  • Cosmetic issues in monitoring/tooling
  • Non-critical feature differences
  • Issues with clear workarounds

Appendix A: Quick Reference Card

Essential Commands

-- Connect to HeliosDB via Oracle protocol
sqlplus admin/password@//heliosdb:1521/heliosdb
-- Check Oracle compatibility mode
SELECT SYS_CONTEXT('USERENV', 'DB_NAME') FROM DUAL;
-- View active sessions
SELECT * FROM v$session WHERE type = 'USER';
-- Check PL/SQL compilation
SHOW ERRORS PROCEDURE <name>;
-- Analyze performance
EXPLAIN PLAN FOR <query>;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

Configuration Files

FileLocationPurpose
tnsnames.ora$TNS_ADMIN/Connection aliases
heliosdb.toml/etc/heliosdb/Server configuration
listener.ora$TNS_ADMIN/Not needed for HeliosDB

Support Resources

  • HeliosDB Oracle Protocol Documentation: /docs/reference/protocols/oracle/
  • Migration Tools: heliosdb migrate --help
  • Support: support@heliosdb.io

Appendix B: Migration Timeline Template

WeekPhaseActivities
1AssessmentInventory, complexity analysis
2PlanningDesign migration strategy, create test plan
3-4Schema MigrationExport DDL, translate, create in HeliosDB
5-6Data MigrationInitial data load, verify
7-8PL/SQL MigrationConvert procedures, functions, packages
9TestingFunctional testing, performance testing
10Parallel RunDual-write, validate
11CutoverSwitch primary to HeliosDB
12StabilizationMonitor, optimize, close out

Related Documentation:


Document History:

  • v1.0 (January 2026): Initial comprehensive guide