Apache Ignite SQL API 深度解析与实战指南
ignite Apache Ignite 项目地址: https://gitcode.com/gh_mirrors/ignite4/ignite
引言
Apache Ignite 作为一个高性能的内存计算平台,提供了强大的 SQL 查询能力。本文将深入探讨 Ignite 的 SQL API,帮助开发者理解如何通过 Java API 高效地进行数据查询和操作。
SQL API 核心概念
Ignite 的 SQL API 主要通过 SqlFieldsQuery
类实现,它提供了执行 SQL 语句和遍历结果的能力。与 JDBC 驱动相比,SQL API 提供了更直接的编程接口和更灵活的控制能力。
配置可查询字段
在使用 SQL 查询缓存前,必须明确哪些字段可以被 SQL 引擎查询。Ignite 提供了两种配置方式:
1. 使用 @QuerySqlField 注解
在 Java 类中,可以通过注解方式标记可查询字段:
public class Person {
@QuerySqlField
private long id;
@QuerySqlField(index = true) // 带索引的字段
private String name;
@QuerySqlField
private int age;
}
配置缓存时需要通过 setIndexedTypes
方法注册这些类型:
CacheConfiguration<Long, Person> cfg = new CacheConfiguration<>("Person");
cfg.setIndexedTypes(Long.class, Person.class);
2. 使用 QueryEntity 配置
XML 配置方式:
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="Person"/>
<property name="queryEntities">
<list>
<bean class="org.apache.ignite.cache.QueryEntity">
<property name="keyType" value="java.lang.Long"/>
<property name="valueType" value="org.apache.ignite.examples.Person"/>
<property name="fields">
<map>
<entry key="id" value="java.lang.Long"/>
<entry key="name" value="java.lang.String"/>
<entry key="age" value="java.lang.Integer"/>
</map>
</property>
</bean>
</list>
</property>
</bean>
Java 代码配置方式:
QueryEntity entity = new QueryEntity();
entity.setKeyType(Long.class.getName());
entity.setValueType(Person.class.getName());
Map<String, String> fields = new LinkedHashMap<>();
fields.put("id", Long.class.getName());
fields.put("name", String.class.getName());
fields.put("age", Integer.class.getName());
entity.setFields(fields);
CacheConfiguration<Long, Person> cfg = new CacheConfiguration<>("Person");
cfg.setQueryEntities(Arrays.asList(entity));
执行 SQL 查询
基本查询示例
IgniteCache<Long, Person> cache = ignite.cache("Person");
// 创建查询对象
SqlFieldsQuery sql = new SqlFieldsQuery(
"SELECT p.name, p.age FROM Person p WHERE p.age > ?");
// 设置参数
sql.setArgs(30);
// 执行查询
try (QueryCursor<List<?>> cursor = cache.query(sql)) {
for (List<?> row : cursor)
System.out.println("Name: " + row.get(0) + ", Age: " + row.get(1));
}
本地查询模式
对于只需要查询本地节点数据的场景,可以启用本地模式:
SqlFieldsQuery sql = new SqlFieldsQuery("SELECT * FROM Person");
sql.setLocal(true); // 仅查询本地节点数据
注意:本地查询不会获取集群中其他节点的数据,结果可能不完整。
DML 操作
Ignite SQL API 支持完整的 DML 操作:
插入数据
SqlFieldsQuery sql = new SqlFieldsQuery(
"INSERT INTO Person(id, name, age) VALUES(?, ?, ?)");
sql.setArgs(1L, "John Doe", 35);
cache.query(sql).getAll(); // 必须调用 getAll() 执行 DML
更新数据
SqlFieldsQuery sql = new SqlFieldsQuery(
"UPDATE Person SET age = ? WHERE name = ?");
sql.setArgs(36, "John Doe");
cache.query(sql).getAll();
删除数据
SqlFieldsQuery sql = new SqlFieldsQuery(
"DELETE FROM Person WHERE age < ?");
sql.setArgs(30);
cache.query(sql).getAll();
MERGE 操作
SqlFieldsQuery sql = new SqlFieldsQuery(
"MERGE INTO Person(id, name, age) VALUES(?, ?, ?)");
sql.setArgs(1L, "John Doe", 36);
cache.query(sql).getAll();
模式(Schema)管理
Ignite 支持多模式(Schema)环境:
// 指定模式执行查询
SqlFieldsQuery sql = new SqlFieldsQuery("SELECT * FROM City");
sql.setSchema("Person"); // 查询 Person 模式下的 City 表
// 或者在 SQL 中直接指定
SqlFieldsQuery sql = new SqlFieldsQuery("SELECT * FROM Person.City");
表创建与管理
通过 SQL API 可以动态创建表:
// 创建 City 表
String createCityTable = "CREATE TABLE IF NOT EXISTS City (" +
"id LONG PRIMARY KEY, name VARCHAR, region VARCHAR) WITH " +
"template=replicated, backups=1";
cache.query(new SqlFieldsQuery(createCityTable).setSchema("Person")).getAll();
高级查询特性
子查询处理
Ignite 对 WHERE 子句中的子查询有特殊处理:
DELETE FROM Person WHERE id IN
(SELECT personId FROM Salary WHERE amount > 2000)
在这个例子中,主查询会分布式执行,而子查询(SELECT personId...
)会在本地节点执行。
表连接查询
String joinQuery = "SELECT o.name FROM Organization o " +
"INNER JOIN \"Person\".Person p ON o.id = p.orgId " +
"INNER JOIN City c ON c.name = o.cityName " +
"WHERE p.age > 25 AND c.region <> 'Texas'";
SqlFieldsQuery sql = new SqlFieldsQuery(joinQuery);
sql.setSchema("PUBLIC"); // 设置默认模式
查询控制与取消
设置查询超时
SqlFieldsQuery sql = new SqlFieldsQuery("SELECT * FROM LargeTable");
sql.setTimeout(10, TimeUnit.SECONDS); // 10秒超时
手动取消查询
QueryCursor<List<?>> cursor = cache.query(sql);
// 处理部分结果
for (List<?> row : cursor) {
if (someCondition)
break; // 提前终止
}
cursor.close(); // 显式关闭会取消查询
最佳实践
- 索引优化:为频繁查询的字段添加索引
- 批量操作:对于大批量DML操作,考虑使用批量API
- 查询计划:复杂查询前使用EXPLAIN分析查询计划
- 连接管理:及时关闭查询游标释放资源
- 模式设计:合理规划模式结构提高查询效率
总结
Apache Ignite 的 SQL API 提供了强大而灵活的数据访问能力,既支持标准SQL语法,又能充分利用Ignite的分布式特性。通过本文的介绍,开发者应该能够掌握Ignite SQL API的核心概念和使用方法,在实际项目中高效地进行数据查询和操作。
ignite Apache Ignite 项目地址: https://gitcode.com/gh_mirrors/ignite4/ignite
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考