执行Hazelcast SQL JOIN触发AssertionError异常问题咨询
Hazelcast SQL JOIN查询触发AssertionError问题
我在执行以下Hazelcast SQL查询时遇到了断言错误:
private static final String SQL_FIND_BY_CLIENT_CODE = "SELECT c.clientKey " + "FROM client c " + "JOIN client2system c2s on c2s.clientId = c.clientId " + "WHERE c2s.systemId = ? " + "AND c2s.clientCode = ?"; @Autowired private SqlService sqlService; public Client findByClientCode(long systemId, String clientCode) { try (SqlResult result = sqlService.execute(SQL_FIND_BY_CLIENT_CODE, systemId, clientCode)) { ... } }
触发的异常信息如下:
java.lang.AssertionError: class com.hazelcast.jet.sql.impl.opt.physical.IndexScanMapPhysicalRel at com.hazelcast.jet.sql.impl.opt.physical.CreateDagVisitor.onNestedLoopJoin(CreateDagVisitor.java:380) at com.hazelcast.jet.sql.impl.opt.physical.JoinNestedLoopPhysicalRel.accept(JoinNestedLoopPhysicalRel.java:110) at com.hazelcast.jet.sql.impl.opt.physical.CreateDagVisitor.connectInput(CreateDagVisitor.java:494) at com.hazelcast.jet.sql.impl.opt.physical.CreateDagVisitor.connectInputPreserveCollation(CreateDagVisitor.java:536) at com.hazelcast.jet.sql.impl.opt.physical.CreateDagVisitor.onProject(CreateDagVisitor.java:207) at com.hazelcast.jet.sql.impl.opt.physical.ProjectPhysicalRel.accept(ProjectPhysicalRel.java:61) at com.hazelcast.jet.sql.impl.opt.physical.CreateDagVisitor.connectInput(CreateDagVisitor.java:494) at com.hazelcast.jet.sql.impl.opt.physical.CreateDagVisitor.onRoot(CreateDagVisitor.java:470) at com.hazelcast.jet.sql.impl.opt.physical.RootRel.accept(RootRel.java:43) at com.hazelcast.jet.sql.impl.CalciteSqlOptimizer.traverseRel(CalciteSqlOptimizer.java:660) at com.hazelcast.jet.sql.impl.CalciteSqlOptimizer.toPlan(CalciteSqlOptimizer.java:528) at com.hazelcast.jet.sql.impl.CalciteSqlOptimizer.createPlan(CalciteSqlOptimizer.java:283) at com.hazelcast.jet.sql.impl.CalciteSqlOptimizer.prepare(CalciteSqlOptimizer.java:242) at com.hazelcast.sql.impl.SqlServiceImpl.prepare(SqlServiceImpl.java:256) at com.hazelcast.sql.impl.SqlServiceImpl.query0(SqlServiceImpl.java:236) at com.hazelcast.sql.impl.SqlServiceImpl.execute(SqlServiceImpl.java:193) at com.hazelcast.sql.impl.SqlServiceImpl.execute(SqlServiceImpl.java:161) at com.hazelcast.sql.impl.SqlServiceImpl.execute(SqlServiceImpl.java:157) at com.hazelcast.sql.impl.SqlServiceImpl.execute(SqlServiceImpl.java:153) at com.hazelcast.sql.SqlService.execute(SqlService.java:89)
查看Hazelcast源码中CreateDagVisitor类第380行的实现:
public Vertex onNestedLoopJoin(JoinNestedLoopPhysicalRel rel) { assert rel.getRight() instanceof FullScanPhysicalRel : rel.getRight().getClass(); // this is line 380 Table rightTable = rel.getRight().getTable().unwrap(HazelcastTable.class).getTarget(); collectObjectKeys(rightTable); VertexWithInputConfig vertexWithConfig = getJetSqlConnector(rightTable).nestedLoopReader( dag, rightTable, rel.rightFilter(parameterMetadata), rel.rightProjection(parameterMetadata), rel.joinInfo(parameterMetadata) ); Vertex vertex = vertexWithConfig.vertex(); connectInput(rel.getLeft(), vertex, vertexWithConfig.configureEdgeFn()); return vertex; }
可以明确看到,Hazelcast的嵌套连接逻辑预期右表扫描类型为FullScanPhysicalRel,但实际优化器生成的是IndexScanMapPhysicalRel实例,直接触发断言失败。
环境配置
- Hazelcast版本:5.1
- Maven依赖配置:
<properties> <version.hazelcast>5.1</version.hazelcast> </properties> ... <dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast-spring</artifactId> <version>${version.hazelcast}</version> </dependency> <dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast</artifactId> <version>${version.hazelcast}</version> </dependency> <dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast-sql</artifactId> <version>${version.hazelcast}</version> </dependency>
注:client和client2system均为IMap,通过以下代码暴露给SQL:
@Bean public SqlService sqlService(HazelcastInstance hazelcastInstance) { SqlService sqlService = hazelcastInstance.getSql(); Map<String, Class<?>> configMap = Map.of( "client", Client.class, "client2system", Client2System.class, ); configMap.forEach((name, type) -> { sqlService.execute(String.format("CREATE MAPPING \"%s\" TYPE IMap OPTIONS ('keyFormat' = 'java', 'keyJavaClass' = 'java.lang.Long', 'valueFormat' = 'java', 'valueJavaClass' = '%s' )", name, type.getName())); }); return sqlService; }
解决方案建议
- 强制全表扫描:在SQL中添加查询提示,强制优化器对右表使用全表扫描,绕过索引扫描逻辑:
SELECT /*+ FULL_SCAN(c2s) */ c.clientKey FROM client c JOIN client2system c2s on c2s.clientId = c.clientId WHERE c2s.systemId = ? AND c2s.clientCode = ?
- 升级版本:该断言错误在Hazelcast 5.1.1及后续版本中已被修复,升级到新版本可彻底解决问题。
内容的提问来源于stack exchange,提问作者lance-java
相关产品推荐
相关产品推荐

