Fix Ignite 3.1 SQL Join query performance issue (Step-by-Step Guide)
🚨 Understanding the Error
Section titled “🚨 Understanding the Error”In Apache Ignite 3.1, SQL Join query performance issues typically manifest as high latency, excessive CPU utilization on specific nodes, or OutOfMemoryError during large result set processing. Unlike Ignite 2.x, Ignite 3 utilizes a high-performance Calcite-based SQL engine. When a Join query performs poorly, it usually indicates that the optimizer is failing to find an efficient execution path, resulting in a Broadcast Join (sending the entire table to all nodes) or a massive Data Shuffle (re-partitioning data across the cluster at runtime).
🔍 Root Cause
Section titled “🔍 Root Cause”The following table outlines the most common technical triggers for degraded Join performance in Ignite 3.1:
| Cause | Explanation |
|---|---|
| Non-Colocated Joins | Join keys do not match the Colocation Keys defined in the table schema, forcing data movement across the network. |
| Stale Statistics | The Cost-Based Optimizer (CBO) lacks updated information on row counts and distribution, leading to suboptimal plan selection. |
| Index Scans vs. Table Scans | Lack of secondary indexes on join predicates forces the engine into a nested loop join with full table scans. |
| Implicit Type Casting | Joining columns with different data types (e.g., INT vs BIGINT) prevents the optimizer from utilizing indexes. |
| Memory Pressure | Insufficient memory allocated to the SQL execution engine causes disk spilling or GC thrashing. |
🛠️ Step-by-Step Solutions
Section titled “🛠️ Step-by-Step Solutions”1. Analyze the Execution Plan
Section titled “1. Analyze the Execution Plan”Before making changes, identify if the engine is performing a MAPREDUCE operation or a heavy SHUFFLE. Use the EXPLAIN keyword to inspect the plan.
EXPLAIN PLAN FORSELECT e.name, d.department_nameFROM Employee eJOIN Department d ON e.dept_id = d.id;Look for IgniteExchange or IgniteSortMergeJoin in the output. If you see high cost values or unexpected broadcasts, proceed to the next steps.
2. Implement Data Colocation
Section titled “2. Implement Data Colocation”In Ignite 3, colocation is the primary way to ensure Joins happen locally on the same node. Ensure that the joining keys are defined as the COLOCATE BY keys during table creation.
-- Table 1: Primary key and colocation key is 'id'CREATE TABLE Department ( id INT, department_name VARCHAR, PRIMARY KEY (id)) COLOCATE BY (id);
-- Table 2: Use 'dept_id' as colocation key to match Department.idCREATE TABLE Employee ( id INT, dept_id INT, name VARCHAR, PRIMARY KEY (id, dept_id)) COLOCATE BY (dept_id);3. Update Table Statistics
Section titled “3. Update Table Statistics”The Calcite engine relies on metadata to decide between Hash Join and Nested Loop. If statistics are missing, it defaults to heuristics which may be incorrect. Run the ANALYZE command.
# Execute via Ignite CLI or SQL toolANALYZE Department;ANALYZE Employee;4. Create Secondary Indexes
Section titled “4. Create Secondary Indexes”For non-equijoins or complex predicates, ensure that the columns used in the ON and WHERE clauses are indexed to avoid TableScan.
CREATE INDEX idx_employee_dept ON Employee (dept_id);5. Check for Type Mismatches
Section titled “5. Check for Type Mismatches”Verify that the data types of the joined columns are identical. If Employee.dept_id is a BIGINT and Department.id is an INT, the index will be ignored.
-- Bad: Implicit castSELECT * FROM TableA a JOIN TableB b ON a.int_col = b.bigint_col;
-- Good: Exact matchesALTER TABLE TableA ALTER COLUMN int_col SET DATA TYPE BIGINT;🛡️ Prevention and Best Practices
Section titled “🛡️ Prevention and Best Practices”To maintain high SQL performance in Ignite 3.1, integrate these practices into your development lifecycle:
- Define Colocation Early: Design your schema around Join patterns. Changing colocation keys later requires table recreation and data migration.
- Monitor Distribution Zones: Use Ignite 3 Distribution Zones to ensure that related tables are stored across the same set of data nodes.
- Automate ANALYZE: Schedule a task to run
ANALYZEafter significant data ingestion to keep the Cost-Based Optimizer accurate. - Use SQL Benchmarking: Before deploying complex Joins to production, use the Ignite CLI to measure execution time with representative data volumes.
- Limit Result Sets: Always use
LIMITorFETCH FIRSTfor analytical queries to prevent the SQL engine from saturating the heap during the merge phase.
Press Ctrl + C in your CLI if you need to terminate a runaway long-running query before it impacts cluster stability.