0
# Query Compilation
1
2
Phoenix's query compilation framework transforms SQL statements into optimized execution plans that leverage HBase's distributed architecture. This system provides query optimization, predicate pushdown, and efficient execution planning.
3
4
## Core Imports
5
6
```java
7
import org.apache.phoenix.query.*;
8
import org.apache.phoenix.compile.*;
9
import org.apache.phoenix.schema.*;
10
import org.apache.phoenix.expression.*;
11
```
12
13
## Query Services
14
15
### QueryServices
16
17
Base interface defining core Phoenix query services and configuration.
18
19
```java{ .api }
20
public interface QueryServices {
21
Configuration getConfiguration()
22
void close() throws SQLException
23
Props getProps()
24
StatsManager getStatsManager()
25
}
26
```
27
28
### QueryServicesImpl
29
30
Main implementation of Phoenix query services.
31
32
```java{ .api }
33
public class QueryServicesImpl implements QueryServices {
34
public QueryServicesImpl(Configuration config, Props props)
35
public Configuration getConfiguration()
36
public Props getProps()
37
public StatsManager getStatsManager()
38
}
39
```
40
41
**Usage:**
42
```java
43
Configuration config = HBaseConfiguration.create();
44
Props props = Props.create();
45
QueryServices queryServices = new QueryServicesImpl(config, props);
46
```
47
48
### ConnectionQueryServices
49
50
Connection-specific query services providing metadata operations, table management, and HBase integration.
51
52
```java{ .api }
53
public interface ConnectionQueryServices extends QueryServices, MetaDataMutated {
54
// Table operations
55
PTable getTable(PName tableName) throws SQLException
56
TableDescriptor getTableDescriptor(byte[] tableName) throws SQLException
57
58
// Metadata operations
59
long getMetaDataMutated(PName schemaName, PName tableName, long tableSeqNum)
60
throws SQLException
61
62
// Admin operations
63
Admin getAdmin() throws SQLException
64
void dropTable(PName tableName) throws SQLException
65
66
// Statistics operations
67
void updateStatistics(List<Mutation> statsTable) throws SQLException
68
69
// Index operations
70
void createIndex(CreateIndexStatement statement, boolean allocateIndexId)
71
throws SQLException
72
void dropIndex(PName schemaName, PName indexName, PName tableName, long timestamp)
73
throws SQLException
74
}
75
```
76
77
### ConnectionQueryServicesImpl
78
79
Main implementation of connection query services.
80
81
```java{ .api }
82
public class ConnectionQueryServicesImpl extends QueryServicesImpl
83
implements ConnectionQueryServices {
84
public ConnectionQueryServicesImpl(Configuration config, ConnectionInfo connectionInfo)
85
public PTable getTable(PName tableName) throws SQLException
86
public Admin getAdmin() throws SQLException
87
public long getMetaDataMutated(PName schemaName, PName tableName, long tableSeqNum)
88
}
89
```
90
91
**Usage:**
92
```java
93
ConnectionInfo connInfo = ConnectionInfo.create("jdbc:phoenix:localhost:2181");
94
ConnectionQueryServices queryServices = new ConnectionQueryServicesImpl(config, connInfo);
95
96
// Access table metadata
97
PName tableName = PNameFactory.newName("users");
98
PTable table = queryServices.getTable(tableName);
99
100
// Get HBase admin
101
Admin admin = queryServices.getAdmin();
102
```
103
104
### ConnectionlessQueryServicesImpl
105
106
Query services implementation for connectionless mode (typically used for testing).
107
108
```java{ .api }
109
public class ConnectionlessQueryServicesImpl implements ConnectionQueryServices {
110
public ConnectionlessQueryServicesImpl(Configuration config, Props props)
111
112
// Provides minimal implementation without HBase connectivity
113
public PTable getTable(PName tableName) throws SQLException
114
public Admin getAdmin() throws SQLException
115
}
116
```
117
118
## Query Plans
119
120
### QueryPlan
121
122
Base interface for all query execution plans.
123
124
```java{ .api }
125
public interface QueryPlan {
126
StatementContext getContext()
127
ParameterMetaData getParameterMetaData()
128
ExplainPlan getExplainPlan() throws SQLException
129
ResultIterator iterator() throws SQLException
130
long getEstimatedSize()
131
Cost getCost()
132
}
133
```
134
135
### StatementPlan
136
137
Interface for statement execution plans.
138
139
```java{ .api }
140
public interface StatementPlan extends QueryPlan {
141
Operation getOperation()
142
StatementType getStatementType()
143
}
144
```
145
146
### MutationPlan
147
148
Interface for data mutation plans (INSERT, UPDATE, DELETE).
149
150
```java{ .api }
151
public interface MutationPlan extends StatementPlan {
152
MutationState execute() throws SQLException
153
long getEstimatedRowsToScan()
154
Long getEstimatedBytesToScan()
155
}
156
```
157
158
**Usage:**
159
```java
160
// Compile a query plan
161
QueryCompiler compiler = new QueryCompiler();
162
String sql = "SELECT * FROM users WHERE age > ?";
163
QueryPlan plan = compiler.compile(sql, context);
164
165
// Analyze the plan
166
ExplainPlan explainPlan = plan.getExplainPlan();
167
long estimatedSize = plan.getEstimatedSize();
168
169
// Execute the plan
170
ResultIterator iterator = plan.iterator();
171
```
172
173
## Compilation Framework
174
175
### QueryCompiler
176
177
Main query compilation engine that transforms SQL into execution plans.
178
179
```java{ .api }
180
public class QueryCompiler {
181
public QueryPlan compile(SelectStatement select, StatementContext context)
182
throws SQLException
183
public QueryPlan compile(String sql, StatementContext context) throws SQLException
184
public MutationPlan compile(UpsertStatement upsert, StatementContext context)
185
throws SQLException
186
public QueryPlan compileJoin(SelectStatement select, StatementContext context)
187
throws SQLException
188
}
189
```
190
191
**Usage:**
192
```java
193
QueryCompiler compiler = new QueryCompiler();
194
StatementContext context = new StatementContext(connection, resolver);
195
196
// Compile SELECT statement
197
String selectSql = "SELECT id, name FROM users WHERE status = 'ACTIVE' ORDER BY created_date";
198
QueryPlan selectPlan = compiler.compile(selectSql, context);
199
200
// Compile INSERT statement
201
String upsertSql = "UPSERT INTO users (id, name, status) VALUES (?, ?, ?)";
202
MutationPlan upsertPlan = compiler.compile(parseUpsert(upsertSql), context);
203
```
204
205
### ExpressionCompiler
206
207
Compiles SQL expressions into Phoenix expression objects.
208
209
```java{ .api }
210
public class ExpressionCompiler extends ParseNodeVisitor<Expression> {
211
public ExpressionCompiler(StatementContext context)
212
public ExpressionCompiler(StatementContext context, GroupBy groupBy)
213
214
public Expression visit(LiteralParseNode node) throws SQLException
215
public Expression visit(ColumnParseNode node) throws SQLException
216
public Expression visit(FunctionParseNode node) throws SQLException
217
public Expression visit(ComparisonParseNode node) throws SQLException
218
}
219
```
220
221
**Usage:**
222
```java
223
StatementContext context = new StatementContext(connection, resolver);
224
ExpressionCompiler exprCompiler = new ExpressionCompiler(context);
225
226
// Compile individual expressions
227
ParseNode literalNode = new LiteralParseNode("'active'");
228
Expression literalExpr = exprCompiler.visit(literalNode);
229
230
ParseNode columnNode = new ColumnParseNode(null, "status", null);
231
Expression columnExpr = exprCompiler.visit(columnNode);
232
```
233
234
### SelectStatement
235
236
Compiled representation of SELECT statements.
237
238
```java{ .api }
239
public class SelectStatement implements FilterableStatement {
240
public SelectStatement(FromClause from, HintNode hint, boolean distinct,
241
List<AliasedNode> select, ParseNode where,
242
List<ParseNode> groupBy, ParseNode having,
243
List<OrderByNode> orderBy, LimitNode limit)
244
245
public FromClause getFrom()
246
public List<AliasedNode> getSelect()
247
public ParseNode getWhere()
248
public List<ParseNode> getGroupBy()
249
public List<OrderByNode> getOrderBy()
250
public LimitNode getLimit()
251
}
252
```
253
254
## Statement Compilers
255
256
### CreateTableCompiler
257
258
Compiler for CREATE TABLE statements.
259
260
```java{ .api }
261
public class CreateTableCompiler {
262
public MutationPlan compile(CreateTableStatement create) throws SQLException
263
264
public static class CreateTableMutationPlan implements MutationPlan {
265
public MutationState execute() throws SQLException
266
public ExplainPlan getExplainPlan() throws SQLException
267
public StatementContext getContext()
268
}
269
}
270
```
271
272
### CreateIndexCompiler
273
274
Compiler for CREATE INDEX statements.
275
276
```java{ .api }
277
public class CreateIndexCompiler {
278
public MutationPlan compile(CreateIndexStatement create) throws SQLException
279
280
public static class CreateIndexMutationPlan implements MutationPlan {
281
public MutationState execute() throws SQLException
282
public long getEstimatedRowsToScan()
283
public Long getEstimatedBytesToScan()
284
}
285
}
286
```
287
288
### CreateSchemaCompiler
289
290
Compiler for CREATE SCHEMA statements.
291
292
```java{ .api }
293
public class CreateSchemaCompiler {
294
public MutationPlan compile(CreateSchemaStatement create) throws SQLException
295
296
public static class CreateSchemaMutationPlan implements MutationPlan {
297
public MutationState execute() throws SQLException
298
public StatementType getStatementType()
299
}
300
}
301
```
302
303
### CreateSequenceCompiler
304
305
Compiler for CREATE SEQUENCE statements.
306
307
```java{ .api }
308
public class CreateSequenceCompiler {
309
public MutationPlan compile(CreateSequenceStatement sequence) throws SQLException
310
311
public static class CreateSequenceMutationPlan implements MutationPlan {
312
public MutationState execute() throws SQLException
313
public long getEstimatedRowsToScan()
314
}
315
}
316
```
317
318
### CreateFunctionCompiler
319
320
Compiler for CREATE FUNCTION statements.
321
322
```java{ .api }
323
public class CreateFunctionCompiler {
324
public MutationPlan compile(CreateFunctionStatement function) throws SQLException
325
326
public static class CreateFunctionMutationPlan implements MutationPlan {
327
public MutationState execute() throws SQLException
328
public StatementContext getContext()
329
}
330
}
331
```
332
333
**Usage:**
334
```java
335
// Compile CREATE TABLE statement
336
CreateTableCompiler tableCompiler = new CreateTableCompiler();
337
CreateTableStatement createTable = parseCreateTable(
338
"CREATE TABLE users (id BIGINT PRIMARY KEY, name VARCHAR, email VARCHAR)"
339
);
340
MutationPlan tablePlan = tableCompiler.compile(createTable);
341
tablePlan.execute();
342
343
// Compile CREATE INDEX statement
344
CreateIndexCompiler indexCompiler = new CreateIndexCompiler();
345
CreateIndexStatement createIndex = parseCreateIndex(
346
"CREATE INDEX user_email_idx ON users (email)"
347
);
348
MutationPlan indexPlan = indexCompiler.compile(createIndex);
349
indexPlan.execute();
350
```
351
352
## Column and Expression Handling
353
354
### ColumnProjector
355
356
Projects columns in query results.
357
358
```java{ .api }
359
public class ColumnProjector {
360
public ColumnProjector(String name, String tableName, String familyName,
361
String columnName, Expression expression, boolean caseSensitive)
362
363
public String getName()
364
public Expression getExpression()
365
public String getTableName()
366
public String getFamilyName()
367
public String getColumnName()
368
}
369
```
370
371
### ColumnResolver
372
373
Resolves column references in SQL expressions.
374
375
```java{ .api }
376
public interface ColumnResolver {
377
List<TableRef> getTables()
378
TableRef resolveTable(String schemaName, String tableName) throws SQLException
379
ColumnRef resolveColumn(String schemaName, String tableName, String colName)
380
throws SQLException
381
}
382
```
383
384
### ExpressionProjector
385
386
Projects expressions in query results.
387
388
```java{ .api }
389
public class ExpressionProjector extends ColumnProjector {
390
public ExpressionProjector(String name, String tableName, Expression expression,
391
boolean isCaseSensitive)
392
393
public boolean hasValueExpression()
394
public KeyValueColumnExpression getKeyValueColumnExpression()
395
}
396
```
397
398
**Usage:**
399
```java
400
// Set up column resolver
401
ColumnResolver resolver = new MyColumnResolver(tables);
402
403
// Create column projector
404
Expression nameExpr = new ColumnExpression(nameColumn);
405
ColumnProjector nameProjector = new ColumnProjector(
406
"name", "users", "cf", "name", nameExpr, false
407
);
408
409
// Create expression projector
410
Expression upperNameExpr = new UpperFunction(Arrays.asList(nameExpr));
411
ExpressionProjector upperProjector = new ExpressionProjector(
412
"upper_name", "users", upperNameExpr, false
413
);
414
```
415
416
## Query Context and State
417
418
### StatementContext
419
420
Maintains state and context during query compilation and execution.
421
422
```java{ .api }
423
public class StatementContext {
424
public StatementContext(PhoenixConnection connection)
425
public StatementContext(PhoenixConnection connection, ColumnResolver resolver)
426
427
public PhoenixConnection getConnection()
428
public ColumnResolver getResolver()
429
public Scan getScan()
430
public SequenceManager getSequenceManager()
431
public GroupBy getGroupBy()
432
public OrderBy getOrderBy()
433
}
434
```
435
436
### CompilableStatement
437
438
Interface for statements that can be compiled into execution plans.
439
440
```java{ .api }
441
public interface CompilableStatement extends BindableStatement {
442
QueryPlan compilePlan(StatementContext context, Sequence.ValueOp seqAction)
443
throws SQLException
444
Operation getOperation()
445
}
446
```
447
448
**Usage:**
449
```java
450
// Create statement context
451
PhoenixConnection connection = getPhoenixConnection();
452
ColumnResolver resolver = createResolver(connection);
453
StatementContext context = new StatementContext(connection, resolver);
454
455
// Configure context
456
Scan scan = context.getScan();
457
scan.setCaching(1000);
458
scan.setBatch(100);
459
460
// Use context for compilation
461
QueryCompiler compiler = new QueryCompiler();
462
QueryPlan plan = compiler.compile(selectStatement, context);
463
```
464
465
## Advanced Compilation Features
466
467
### Query Optimization
468
469
```java
470
// Cost-based optimization
471
public class CostBasedOptimizer {
472
public QueryPlan optimize(QueryPlan plan, StatementContext context) throws SQLException
473
public Cost estimateCost(QueryPlan plan) throws SQLException
474
}
475
476
// Usage
477
CostBasedOptimizer optimizer = new CostBasedOptimizer();
478
QueryPlan optimizedPlan = optimizer.optimize(originalPlan, context);
479
Cost estimatedCost = optimizer.estimateCost(optimizedPlan);
480
```
481
482
### Predicate Pushdown
483
484
```java
485
// Pushdown optimization for server-side filtering
486
public class PredicatePushdownOptimizer {
487
public Scan optimizeScan(Scan scan, Expression whereClause)
488
public Filter createPushdownFilter(Expression expression)
489
}
490
491
// Usage
492
PredicatePushdownOptimizer pushdown = new PredicatePushdownOptimizer();
493
Scan optimizedScan = pushdown.optimizeScan(originalScan, whereExpression);
494
```
495
496
### Join Optimization
497
498
```java
499
// Join strategy selection and optimization
500
public class JoinCompiler {
501
public QueryPlan compileJoin(SelectStatement select, StatementContext context)
502
throws SQLException
503
public JoinStrategy selectJoinStrategy(SelectStatement select)
504
}
505
506
// Usage
507
JoinCompiler joinCompiler = new JoinCompiler();
508
QueryPlan joinPlan = joinCompiler.compileJoin(joinSelect, context);
509
```
510
511
## Practical Examples
512
513
### Basic Query Compilation
514
515
```java
516
// Set up compilation environment
517
PhoenixConnection connection = getConnection();
518
ColumnResolver resolver = createTableResolver(connection, "users");
519
StatementContext context = new StatementContext(connection, resolver);
520
521
// Compile a simple query
522
QueryCompiler compiler = new QueryCompiler();
523
String sql = "SELECT id, name FROM users WHERE status = 'ACTIVE'";
524
SelectStatement select = parseSelect(sql);
525
QueryPlan plan = compiler.compile(select, context);
526
527
// Examine the plan
528
ExplainPlan explainPlan = plan.getExplainPlan();
529
System.out.println("Query Plan: " + explainPlan.toString());
530
531
// Execute the plan
532
ResultIterator iterator = plan.iterator();
533
```
534
535
### Complex Query with Aggregation
536
537
```java
538
// Compile aggregation query
539
String aggregateSql = """
540
SELECT department, COUNT(*), AVG(salary), MAX(hire_date)
541
FROM employees
542
WHERE status = 'ACTIVE'
543
GROUP BY department
544
HAVING COUNT(*) > 10
545
ORDER BY department
546
""";
547
548
QueryPlan aggPlan = compiler.compile(aggregateSql, context);
549
Cost cost = aggPlan.getCost();
550
long estimatedSize = aggPlan.getEstimatedSize();
551
552
System.out.println("Estimated cost: " + cost);
553
System.out.println("Estimated size: " + estimatedSize + " bytes");
554
```
555
556
### DDL Statement Compilation
557
558
```java
559
// Compile CREATE TABLE statement
560
CreateTableCompiler tableCompiler = new CreateTableCompiler();
561
String createTableSql = """
562
CREATE TABLE orders (
563
order_id BIGINT NOT NULL,
564
customer_id BIGINT NOT NULL,
565
order_date DATE,
566
amount DECIMAL(10,2),
567
status VARCHAR(20),
568
CONSTRAINT pk PRIMARY KEY (order_id)
569
)
570
""";
571
572
CreateTableStatement createTable = parseCreateTable(createTableSql);
573
MutationPlan tablePlan = tableCompiler.compile(createTable);
574
575
// Execute the DDL
576
MutationState result = tablePlan.execute();
577
```
578
579
### Index Creation
580
581
```java
582
// Compile CREATE INDEX statement
583
CreateIndexCompiler indexCompiler = new CreateIndexCompiler();
584
String createIndexSql = "CREATE INDEX order_customer_idx ON orders (customer_id, order_date)";
585
586
CreateIndexStatement createIndex = parseCreateIndex(createIndexSql);
587
MutationPlan indexPlan = indexCompiler.compile(createIndex);
588
589
// Check estimated work
590
long estimatedRows = indexPlan.getEstimatedRowsToScan();
591
Long estimatedBytes = indexPlan.getEstimatedBytesToScan();
592
593
System.out.println("Index will scan approximately " + estimatedRows + " rows");
594
System.out.println("Index will scan approximately " + estimatedBytes + " bytes");
595
596
// Execute index creation
597
MutationState indexResult = indexPlan.execute();
598
```