The standard approach to analytics on a transactional database is to extract data to a separate system. ETL pipelines move data from MySQL to a data warehouse. Reports run on the warehouse, not the production database. This works but it introduces lag, pipeline complexity, schema drift, and another system to operate. For many workloads, the data in the warehouse is already hours old by the time anyone queries it.
OCI MySQL HeatWave changes the architecture. HeatWave is an in-memory query accelerator that attaches directly to your MySQL Database Service instance. OLTP queries continue running against the MySQL storage engine as normal. Analytics queries are automatically offloaded to the HeatWave cluster, which processes them in parallel across its nodes using columnar in-memory storage. No ETL. No separate warehouse. No data movement. Analytical queries that take minutes on a standard MySQL instance complete in seconds on HeatWave.
This post covers deploying MySQL HeatWave with Terraform, loading tables into the HeatWave cluster, running queries, using HeatWave AutoML, and monitoring cluster performance.
Architecture
Application (OLTP writes and reads) | MySQL Database Service (InnoDB engine) | HeatWave Cluster (in-memory columnar store) [node-1] [node-2] [node-3] | Analytics / Reporting / AutoML
The MySQL instance and HeatWave cluster share the same endpoint. Your application connects to MySQL as normal. When a query is better served by HeatWave, the MySQL optimizer routes it to the cluster automatically. You do not change your connection string or query patterns.
Step 1: IAM Policy
resource "oci_identity_policy" "mysql_heatwave_policy" { compartment_id = var.compartment_id name = "mysql-heatwave-policy" description = "Permissions for MySQL HeatWave deployment and management" statements = [ "Allow group ${var.dba_group_name} to manage mysql-family in compartment id ${var.compartment_id}", "Allow group ${var.dba_group_name} to manage virtual-network-family in compartment id ${var.compartment_id}", "Allow group ${var.app_group_name} to use mysql-family in compartment id ${var.compartment_id}", "Allow service mysqlcsn to use virtual-network-family in compartment id ${var.compartment_id}" ]}
Step 2: MySQL Database Service with HeatWave
resource "oci_mysql_mysql_db_system" "heatwave_db" { compartment_id = var.compartment_id display_name = "production-heatwave-db" description = "MySQL HeatWave for transactional and analytical workloads" availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name subnet_id = var.private_subnet_id shape_name = "MySQL.HeatWave.VM.Standard.E3" admin_username = "mysqladmin" admin_password = var.mysql_admin_password data_storage_size_in_gb = 512 is_highly_available = true mysql_version = "8.0.32" port = 3306 port_x = 33060 backup_policy { is_enabled = true retention_in_days = 7 window_start_time = "02:00" pitr_policy { is_enabled = true } } maintenance { window_start_time = "sun 03:00" } deletion_policy { automatic_backup_retention = "RETAIN" final_backup = "REQUIRE_FINAL_BACKUP" is_delete_protected = true } defined_tags = { "Operations.Environment" = "production" "Operations.ManagedBy" = "terraform" }}# HeatWave cluster attached to the DB systemresource "oci_mysql_heat_wave_cluster" "heatwave_cluster" { db_system_id = oci_mysql_mysql_db_system.heatwave_db.id cluster_size = 3 shape_name = "MySQL.HeatWave.VM.Standard.E3"}output "mysql_endpoint" { value = oci_mysql_mysql_db_system.heatwave_db.endpoints[0].hostname description = "MySQL connection hostname"}
The shape_name = "MySQL.HeatWave.VM.Standard.E3" must be specified on both the DB system and the HeatWave cluster and they must match. HeatWave shapes are distinct from standard MySQL shapes and include the memory capacity required for the in-memory columnar store.
The cluster_size = 3 provisions three HeatWave nodes. Each node holds a partition of the data loaded into the cluster. More nodes means more data fits in memory and queries parallelize across more workers. Start with the minimum that fits your dataset and scale up as it grows.
Step 3: Loading Tables into HeatWave
Tables are not automatically loaded into HeatWave. You explicitly load each table using the ALTER TABLE statement with the SECONDARY_ENGINE=RAPID attribute, which designates it for HeatWave storage.
-- Connect to MySQL and run these statements-- Mark tables for HeatWave loadingALTER TABLE orders.order_header SECONDARY_ENGINE=RAPID;ALTER TABLE orders.order_lines SECONDARY_ENGINE=RAPID;ALTER TABLE products.catalog SECONDARY_ENGINE=RAPID;ALTER TABLE customers.profiles SECONDARY_ENGINE=RAPID;-- Load the tables into the HeatWave clusterALTER TABLE orders.order_header SECONDARY_LOAD;ALTER TABLE orders.order_lines SECONDARY_LOAD;ALTER TABLE products.catalog SECONDARY_LOAD;ALTER TABLE customers.profiles SECONDARY_LOAD;-- Verify load statusSELECT NAME, LOAD_STATUSFROM performance_schema.rpd_tablesJOIN performance_schema.rpd_table_id USING (ID)WHERE LOAD_STATUS = 'AVAIL_RPDGSTABSTATE';
Tables with LOAD_STATUS = 'AVAIL_RPDGSTABSTATE' are fully loaded and available for HeatWave query processing. The load time depends on table size. A 100GB table typically loads in a few minutes across a three-node cluster.
For tables that receive frequent writes, HeatWave maintains propagation automatically. Changes committed to InnoDB are propagated to the HeatWave cluster within seconds, keeping analytical queries consistent with the transactional data.
Step 4: Query Routing and Validation
The MySQL optimizer decides which engine to use for each query. You can verify a query is routed to HeatWave using EXPLAIN:
-- Check if a query uses HeatWaveEXPLAIN SELECT c.region, COUNT(DISTINCT o.customer_id) AS unique_customers, SUM(ol.quantity * ol.unit_price) AS total_revenue, AVG(ol.quantity * ol.unit_price) AS avg_order_valueFROM orders.order_header o JOIN orders.order_lines ol ON o.order_id = ol.order_id JOIN customers.profiles c ON o.customer_id = c.customer_idWHERE o.order_date BETWEEN '2026-01-01' AND '2026-06-30' AND o.status = 'COMPLETED'GROUP BY c.regionORDER BY total_revenue DESC;-- Look for "Use secondary engine RAPID" in the Extra column-- This confirms the query is offloaded to HeatWave-- Force a query to HeatWave explicitlySET SESSION use_secondary_engine = FORCED;-- Disable HeatWave for a specific query (for comparison)SET SESSION use_secondary_engine = OFF;SELECT ...;SET SESSION use_secondary_engine = ON;
Run the same analytical query with HeatWave on and off and compare execution times. For aggregation queries across large tables with joins, HeatWave typically delivers 10x to 100x improvement over MySQL running on InnoDB alone.
Step 5: HeatWave AutoML
HeatWave AutoML trains machine learning models directly inside the database using data already loaded into the cluster. No data export, no separate ML platform, no feature engineering pipeline. You call stored procedures that train, evaluate, and deploy models against your MySQL tables.
-- Train a churn prediction model on customer dataCALL sys.ML_TRAIN( 'analytics.customer_features', -- training table 'churned', -- target column JSON_OBJECT( 'task', 'classification', 'optimization_metric', 'accuracy', 'exclude_column_list', JSON_ARRAY('customer_id', 'signup_date') ), @churn_model);-- Check training statusSELECT @churn_model;-- Load the trained model for predictionCALL sys.ML_MODEL_LOAD(@churn_model, NULL);-- Run predictions on new customersCALL sys.ML_PREDICT_TABLE( 'analytics.new_customers', -- input table @churn_model, -- trained model 'analytics.churn_predictions', -- output table JSON_OBJECT('task', 'classification'));-- Review predictionsSELECT customer_id, churned_prediction, churned_probabilityFROM analytics.churn_predictionsORDER BY churned_probability DESCLIMIT 100;-- Get model explanation - feature importanceCALL sys.ML_EXPLAIN_TABLE( 'analytics.new_customers', @churn_model, 'analytics.churn_explanations', JSON_OBJECT('prediction_explainer', 'permutation_importance'));
AutoML supports classification, regression, forecasting, anomaly detection, and recommendation tasks. The model is stored inside the MySQL instance. Predictions are generated by calling sys.ML_PREDICT_ROW for single-row inference or sys.ML_PREDICT_TABLE for batch inference, both of which run inside the database without any external service call.
Step 6: Monitoring HeatWave Performance
resource "oci_monitoring_alarm" "heatwave_node_failure" { compartment_id = var.compartment_id display_name = "heatwave-node-not-active" is_enabled = true metric_compartment_id = var.compartment_id namespace = "oci_mysql_database" query = "HeatWaveNodesActive[5m]{dbSystemId = '${oci_mysql_mysql_db_system.heatwave_db.id}'}.min() 400" severity = "WARNING" pending_duration = "PT5M" destinations = [var.ops_notification_topic_id] body = "MySQL active connections exceeding 400. Review connection pooling configuration."}
Query HeatWave performance from inside MySQL using the performance schema:
-- Active HeatWave queriesSELECT PROCESSLIST_ID, PROCESSLIST_USER, PROCESSLIST_TIME, PROCESSLIST_INFOFROM performance_schema.threadsWHERE PROCESSLIST_STATE LIKE '%rapid%' AND PROCESSLIST_INFO IS NOT NULL;-- HeatWave memory usage per tableSELECT t.NAME AS table_name, ROUND(SUM(c.COLUMN_MEMORY) / 1024 / 1024, 2) AS memory_mbFROM performance_schema.rpd_tables t JOIN performance_schema.rpd_columns c USING (ID)GROUP BY t.NAMEORDER BY memory_mb DESC;-- Query offload statisticsSELECT VARIABLE_NAME, VARIABLE_VALUEFROM performance_schema.global_statusWHERE VARIABLE_NAME IN ( 'rapid_query_offload_count', 'rapid_query_offload_fail_count', 'rapid_query_offload_warn_count' );
HeatWave Lakehouse: Querying Object Storage Directly
HeatWave Lakehouse extends the cluster to query data directly from OCI Object Storage without loading it into MySQL first. Parquet, CSV, and Avro files in Object Storage become queryable using standard SQL through an external table definition.
-- Create an external table pointing to Parquet files in Object StorageCREATE TABLE analytics.historical_orders ( order_id VARCHAR(50), customer_id VARCHAR(50), order_date DATE, total_amount DECIMAL(12,2), region VARCHAR(50), status VARCHAR(20))ENGINE=lakehouseSECONDARY_ENGINE=RAPIDCOMMENT='{"file":[{"par":"https://objectstorage.me-jeddah-1.oraclecloud.com/p/TOKEN/n/NAMESPACE/b/analytics-data/o/historical_orders/"}],"dialect":{"format":"parquet"}}';-- Load the external data into HeatWaveALTER TABLE analytics.historical_orders SECONDARY_LOAD;-- Now join historical Object Storage data with live transactional dataSELECT h.region, h.order_date, COUNT(*) AS historical_orders, SUM(h.total_amount) AS historical_revenue, COUNT(DISTINCT o.order_id) AS current_ordersFROM analytics.historical_orders h LEFT JOIN orders.order_header o ON h.region = ( SELECT region FROM customers.profiles WHERE customer_id = o.customer_id ) AND YEAR(o.order_date) = YEAR(h.order_date)GROUP BY h.region, h.order_dateORDER BY h.order_date DESC, historical_revenue DESC;
This query joins years of historical order data stored as Parquet in Object Storage with live transactional data from the MySQL InnoDB tables, all processed inside HeatWave without any external query engine, ETL pipeline, or data warehouse.
When HeatWave Is the Right Choice
HeatWave solves the problem of needing analytics on fresh data without the operational overhead of a separate analytics platform. It is the right choice when your analytical workload runs on MySQL data, you need results on data that is minutes old rather than hours old, and you want to avoid maintaining an ETL pipeline and a separate data warehouse.
It is not the right choice for multi-source analytics that pull from many different databases, for very large datasets that exceed the in-memory capacity of the cluster, or for organizations that already have a mature data warehouse with established data governance around it.
The operational simplicity is the main argument. One database, one endpoint, one backup policy, one set of IAM policies. OLTP and analytics on the same data, in the same system, with no synchronization lag between them.
Regards,
Osama
#OCI #OracleCloud #MySQL #HeatWave #Terraform #CloudNative #InfrastructureAsCode #IaC #OracleCloudInfrastructure #Analytics #DatabaseEngineering #DevOps #PlatformEngineering #CloudArchitecture #TechBlog #CloudDatabase #OLAP #Oracle #HeatWaveLakehouse #AutoML
Leave a comment