You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 23:10:30