Cassandra cql select 查询总是抛出读取超时异常

标签 cassandra cql datastax-java-driver cqlsh

当我尝试执行以下查询时,我总是收到 QueryTimeOutException,

Exception is,
    com.datastax.driver.core.exceptions.ReadTimeoutException: Cassandra timeout during read query at consistency QUORUM (2 responses were required but only 0 replica responded)

Query is,
    SELECT * FROM my_test.my_table WHERE key_1 = 101 ORDER BY key_2 ASC LIMIT 25;

我使用的是带有 3 个节点的 cassandra 版本 2.1.0,具有 3 个复制的单 DC,cassandra.yaml 具有所有默认值,并且我有以下键空间和表作为架构,

CREATE KEYSPACE my_test
  WITH REPLICATION = { 
    'class' : 'SimpleStrategy', 
    'replication_factor' : 3
};

CREATE TABLE my_test.my_table (
    key_1 bigint,
    key_2 bigint,
    key_3 text,
    key_4 text,
    key_5 text,
    key_6 text,
    key_7 text,
    key_8 text,
    key_9 text,
    key_10 text,
    key_11 timestamp,
    PRIMARY KEY (key_1, key_2)
);

目前该表约有 39000 条记录,但最初有 50000 条记录,由于某些业务逻辑已删除 11000 条记录。

解决方案之一 to avoid such exception is to increase query read time out ,但我的架构和查询是 more direct why should I increase my read time out ? 因为在我的查询中我已经给出了分区键(key_1),所以它应该准确地到达目的地,之后我指定了分区键的开始范围, 所以它应该以 2 秒的最大时间检索,但事实并非如此。但下面的查询工作正常,检索结果不到 1 秒 ( Difference is, ASC is not working and DESC is working )

SELECT * FROM my_test.my_table WHERE key_1 = 101 ORDER BY key_2 DESC LIMIT 25;

同样,根据架构,集群键默认顺序是 ASC,因此根据 cassandra 文档,以 ASC 顺序检索数据应该比 DESC 顺序更快。 但我的情况恰恰相反。


再次提供一些线索,以下是通过 CQLSH 尝试过的查询。

以下查询正在运行,并在不到 1 秒的时间内检索到结果

SELECT * FROM my_test.my_table WHERE key_1 = 101 AND key_2 > 1 AND key_2 < 132645 LIMIT 1;

但是,以下查询不起作用并抛出超时异常,

SELECT * FROM my_test.my_table WHERE key_1 = 101 AND key_2 > 1 AND key_2 < 132646 LIMIT 1;

但是,以下查询正在运行,并且检索结果不到 1 秒

SELECT * FROM my_test.my_table WHERE key_1 = 101 AND key_2 = 132644;
SELECT * FROM my_test.my_table WHERE key_1 = 101 AND key_2 = 132645;
SELECT * FROM my_test.my_table WHERE key_1 = 101 AND key_2 = 132646;
SELECT * FROM my_test.my_table WHERE key_1 = 101 AND key_2 = 132647;

奇怪的行为,任何帮助将不胜感激。

最佳答案

For each key_1 there will be around 1000000 key_2.

当您采用每个分区 20 亿个单元格的限制并尝试使用全部时,就会发生这种情况。我知道我之前已经在这里回答过很多帖子,承认每个分区有 20 亿个单元格的硬性限制,您的(非常)宽的行将变得笨拙,并且可能在此之前超时很长时间 。这就是我相信您所看到的。

这里的解决方案是一种称为“分桶”的技术。基本上,您必须找到一个附加键来对数据进行分区。太多的 CQL 行被写入同一数据分区,分桶有助于将分区与集群键的比率恢复到合理水平。

进行分桶的逻辑方法是使用时间元素。我看到你的最后一个键是时间戳。我不知道每个 key_1 每天获取多少行,但假设您每个月只获取几千行。在这种情况下,我将创建一个额外的分区键 month_bucket:

CREATE TABLE my_test.my_table (
    key_1 bigint,
    key_2 bigint,
    ...
    key_11 timestamp,
    month_bucket text,
    PRIMARY KEY ((key_1,month_bucket) key_2)
);

这将允许您支持这样的查询:

SELECT * FROM my_test.my_table 
WHERE key_1 = 101 AND month_bucket = '201603'
  AND key_2 > 1 AND key_2 < 132646 LIMIT 1;

同样,按月存储只是一个示例。但基本上,您需要找到一个额外的列来对数据进行分区。

关于Cassandra cql select 查询总是抛出读取超时异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36058834/

相关文章:

docker - 将本地 CQL 命令文件传递给 Cassandra Docker 容器

java - `InvalidQueryException: cannot parse ' [B@50908fa9 ' as hex bytes` 使用 Datastax Java 驱动程序

cassandra - cassandra 2.1.2 中的 "Number of Keys"输出中缺少 "nodetool cfstats"。现在如何获取行数?

cassandra - 当我不执行 DELETE 时,为什么有时会有 10,000 多个墓碑?

kubernetes - Spark Cassandra Connector 能否在 K8S 环境中解析来自 headless 服务的主机名?

windows - 启动 Cassandra 服务器错误

java - Cassandra java 驱动程序设置全局一致性级别

apache-spark - 如何使用 Datastax spark-cassandra-connector 从 Cassandra 表中读取特定列?

python - 使用 Python 和 CQL 时如何从 Cassandra 返回时间戳?

python - Pycassa col_fam.get_indexed_slices(clause) 有什么问题