当我尝试执行以下查询时,我总是收到 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/