如何有效地从Cassandra批量选择数据?

时间:2016-11-24 15:50:33

标签: cassandra cql

我知道Cassandra不支持批量查询,也不建议使用IN,因为它会降低性能。但我必须通过id获取数据,例如:

select * from visit where id in ([visit_id array])

desc table:

CREATE TABLE visit (
    enterprise_id int,
    id text,
    ........
    PRIMARY KEY (enterprise_id, id)

阵列可能有数千个元素。有什么办法可以有效地实现吗?

2 个答案:

答案 0 :(得分:4)

我发布这类查询的首选方法是展开 IN部分。这只是意味着你需要并行发出多个查询,因为 token-o-matic (也就是令牌识别)驱动程序会将每个查询视为一个独立的查询,然后将它们传播不同的节点,使每个单个节点成为协调器,负责每个节点的访问。

您应该最多运行 X 查询,并等待至少其中一个查询完成(我使用Java):

final int X = 1000;
ArrayList<ResultSetFuture> futures = new ArrayList<>();
ArrayList<ResultSet> results = new ArrayList<>();
for (int i = 0; i < allTheRowsINeedToFetch; i++) {
    futures.add(session.executeAsync(myBeautifulPreparedStatement.bind(xxx,yyy,zzz)));
    while (futures.size() >= X || (futures.size() > 0 && futures.get(0).isDone())) {
        ResultSetFuture rsf = futures.remove(0);
        results.add(rsf.getUninterruptibly());
    }
}

while (futures.size() > 0) {
    ResultSetFuture rsf = futures.remove(0);
    results.add(rsf.getUninterruptibly());
}

// Now use the results

这称为 backpressure ,它用于压力从群集移动到客户端

这种方法的好处在于你可以真正并行( X = allTheRowsINeedToFetch ),以及真正的串行( X = 1 ),以及所有内容之间只取决于您的群集硬件。较低的 X 值意味着您没有使用足够的群集功能,高值意味着您将会因为您将开始看到而遇到麻烦超时。所以,你真的需要调整它。

答案 1 :(得分:2)

大在查询中创建GC暂停和堆压力,导致整体性能下降。当您执行大查询时,这意味着您正在等待这个单一协调器节点给您一个响应,它将所有这些查询及其响应保留在堆中,如果其中一个查询失败,或者协调器失败,您有重试整个事情。

方法1:

尝试将您的查询转换为范围查询(&gt; =,&lt; =)

SELECT * visit WHERE enterprise_id = ? and id >= ? and id <= ?

方法2:

使用executeAsync,Java示例

PreparedStatement statement = session.prepare("SELECT * FROM visit where enterprise_id = ? and id = ?");

List<ResultSetFuture> futures = new ArrayList<>();
for (int i = 1; i < 4; i++) {
    ResultSetFuture resultSetFuture = session.executeAsync(statement.bind(i, i));
    futures.add(resultSetFuture);
}

List<String> results = new ArrayList<>();
for (ResultSetFuture future : futures){
     ResultSet rows = future.getUninterruptibly();
     Row row = rows.one();
     results.add(row.getString("name"));
}
return results; 

方法3:

如果可能的话,而不是在查询中,创建另一个表,并且当您将在查询中执行的数据即将插入或更新时也将数据插入到新表中,那么您可以在不查询的情况下从新表中查询

资料来源:
http://www.datastax.com/dev/blog/a-deep-look-to-the-cql-where-clause https://lostechies.com/ryansvihla/2014/09/22/cassandra-query-patterns-not-using-the-in-query-for-multiple-partitions/