【问题标题】:Slow range queries in CassandraCassandra 中的慢范围查询
【发布时间】:2017-08-27 09:41:22
【问题描述】:

我正在处理单个节点。我有下表来存储文档列表:

CREATE TABLE my_keyspace.document (
    status text,
    date timestamp,
    doc_id text,
    raw_content text,
    title text,
    PRIMARY KEY (status, date, doc_id)
) WITH CLUSTERING ORDER BY (date ASC, doc_id ASC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
    AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 0
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99PERCENTILE';
CREATE INDEX doc_id_idx ON my_keyspace.document (doc_id);

我正在做很多查询,例如:

SELECT * FROM my_keyspace.document WHERE status='PROCESSED' AND data>=start_date AND data<=end_date;

由于某种原因它非常慢,起初我收到的警告是这样的:

[2016-07-26 18:10:46] {cassandra.protocol:378} WARNING - Server warning: Read 5000 live rows and 19999 tombstone cells for query SELECT * FROM my_keyspace.document WHERE token(status) >= token(PROCESSED) AND token(status) <= token(PROCESSED) AND date >= 2016-07-08 02:00+0200 AND date <= 2016-07-23 01:59+0200 LIMIT 5000 (see tombstone_warn_threshold)
[2016-07-26 18:10:52] {cassandra.protocol:378} WARNING - Server warning: Read 5000 live rows and 19999 tombstone cells for query SELECT * FROM my_keyspace.document WHERE token(status) >= token(PROCESSED) AND token(status) <= token(PROCESSED) AND date >= 2016-07-08 02:00+0200 AND date <= 2016-07-23 01:59+0200 LIMIT 5000 (see tombstone_warn_threshold)

认为这个问题与我做的墓碑太多有关:

ALTER TABLE my_keyspace.document  WITH gc_grace_seconds = '0';

然后:

nodetool compact my_keyspace document

现在我没有任何警告,但查询仍然很慢并且经常超时。任何日志中都没有显示有关超时的消息。我拥有的文档数量大约是 200k 实例。这些文件在 20 天内分发,每天约有 4500 个文件有status='PROCESSED'。查询回答时间因日期范围而异:一天时间范围约为 3 秒,4 天时间范围为 15 秒,超时时间为 2 周。另外,我禁用了交换。我使用的 Cassandra 版本是 3.5。

最近我注意到,使用精确的列而不是 * 来提取可以稍微缩短响应时间,但系统仍然太慢。

编辑:Reveka 提出的计算分区大小

所以,遵循公式:

  • 行数 = 20 * 4500 = 90,000
  • 列数 = 19
  • 主键数 = 3
  • 静态列数 = 0

所以值的数量是 90000*(19-3)=1,440,000

对于分区的大小,我估计约为 1.2GB。 这可能有点大。但是如何修改我的分区键以在拥有较小分区的同时仍然能够执行相同的范围查询?我可以有一个复合分区键,其中包含status 和从date 中提取的日期,但我不必在能够按范围查询之前指定日期:

SELECT * FROM my_keyspace.document WHERE status='PROCESSED' AND day='someday' AND date>='start_date' AND date<='end_date';

这迫使我每天进行一次查询。

【问题讨论】:

    标签: cassandra nosql


    【解决方案1】:

    我看到您的主键由状态、日期和 doc_id 组成,您只使用状态作为分区键。这意味着无论日期如何,所有相同状态的文档都将放在同一个分区中。我想这是一个分区的很多信息。 Cassandra 在 100MB(或更高版本中为几百 MB)大的分区中运行良好,请参阅 here。 Datastax D220 课程(它是免费的,您只需要创建一个帐户)有一个video 向您展示如何计算您的分区大小。您可以将结果发布到您的分析中,以便我们进一步帮助您。 :)

    编辑:尺寸分析后

    您必须按日期进行分区才能拥有更小的分区。这意味着现在您将无法按范围查询。一种解决方法是根据您想要的范围进行多个查询。例如:如果您想查询 8 月 12 日至 8 月 14 日的范围,则按天拆分并执行三个查询,一个针对 8 月 12 日,一个针对 13 日,一个针对 14 日。同样,如果您的范围很大,您将结束检索 gb 数据。我不知道您的用例,但我猜测您每次进行日期范围查询时都不需要 gb 的文件。你能给我更多关于你的用例的信息吗(也就是你想做什么?)

    ps。我还不会写 cmets,所以我只能通过这个答案给你建议

    【讨论】:

    • 我刚刚用分区分析的结果编辑了我的帖子 :)
    猜你喜欢
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 2015-03-10
    • 2013-08-14
    • 2012-03-13
    • 2015-08-18
    • 2015-06-06
    • 1970-01-01
    相关资源
    最近更新 更多