【问题标题】:Optimizing Java Cassandra PreparedStatementCache优化 Java Cassandra PreparedStatementCache
【发布时间】:2019-08-19 08:16:12
【问题描述】:

我使用 org.springframework.data.cassandra.core.cql.support.PreparedStatementCache 来缓存preparedStatement。 但是需要很多内存。 看起来如果我仍然使用 PreparedStatement,缓存永远不会清理并增加(尽管我们使用相同的 cql 查询!!!)。 如果我不再给他打电话,记忆就会减少。

我的应用程序使用 springboot /cassandra dse 我们都在 tomcat 中测试(windows 和 linux 服务器,超过 500 req/s)。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-cassandra</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.datastax.dse</groupId>
                    <artifactId>dse-java-driver-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>



private final PreparedStatementCache cache = PreparedStatementCache.create();

public Channel findByIdChannel(String idChannel) {

        List<Channel> listChannel = cassandraTemplate
                .getCqlOperations()
                .query(
                        findByIdChannelQuery(idChannel),
                        (row, rowNum) -> cassandraTemplate.getConverter().read(Channel.class, row));
        if (listChannel.isEmpty()) {
            return null;
        }
        return listChannel.get(0);
    }

    private BoundStatement findByIdChannelQuery(String idChannel) {
        String cql = "select * from channel where idchannel = '" + idChannel + "'";
        return CachedPreparedStatementCreator.of(
                cache, cql).createPreparedStatement(session)
                .bind();
    }

任何提高性能的建议(不是关于使应用程序缓存和方法级别)? 我们如何修复preparedStatementCache的大小?

非常感谢。

【问题讨论】:

    标签: java cassandra


    【解决方案1】:

    不要为每个 idChannel 都准备好声明。创建一个准备好的语句并绑定 id ,它不必为每个查询创建一个新的(这非常昂贵)。喜欢

      return CachedPreparedStatementCreator.of(
              cache,
              select()
                  .all()
                  .from("channel")
                  .where(eq("idchannel", bindMarker("idchannel")))
          .createPreparedStatement(session)
          .bind()
          .setString("idchannel", idchannel));
    

    【讨论】:

    • 所以你的意思是 PreparedStatementCache 在这种情况下不起作用?他们不是在创建新的之前通过cql在缓存中查找preparedStatement吗?
    • 确实如此,但您的 cql 是 select * from channel where idchannel = '1'; 而不是(基本上)select * from channel where idchannel = ?; 所以每个通道 1,2,3.. 每个通道都有自己的准备好的语句,而不是所有通道的 1。这就是使用准备好的语句的全部意义,减少解析语句和值的开销(诚然非常小)。
    • 感谢您的回答,我已经测试了 2 个案例:- 创建单个preparedstatement 并绑定)并使用相同的 cql(例如 select * from channel where idchannel = '1')。问题始终存在(PreparedStatementCache 占用大量内存,并且看起来像缓存相同的preparedstatement)。有没有办法配置这个变量?他们的驱逐是按时间还是按规模?我对 cassandra 的这个 api 一无所获。
    • Springs 准备好的语句缓存是一个无限的永不过期的映射,如果你不断向它添加新的 CQL,你最终会耗尽内存。如果您有选择,我不会在驱动程序上使用弹簧包装。我建议如果使用 spring 根本不使用准备好的语句,因为该表对性能的积极影响可能甚至无法衡量。
    猜你喜欢
    • 2020-01-19
    • 1970-01-01
    • 2015-03-05
    • 2020-08-29
    • 2016-12-20
    • 2013-05-11
    • 2017-06-28
    • 2019-11-23
    • 2017-08-06
    相关资源
    最近更新 更多