如何在不使用分区键的情况下使用ORDER_BY搜索记录

时间:2019-06-26 00:52:15

标签: cassandra cql

我正在调试问题,日志应该位于4/23/19〜4/25/19之间的时间范围

我们的作品有数亿条记录。 使用随机排序无法找到目标记录。

在没有分区键的时间范围内是否可以进行搜索?

  

从XXXX.report_summary顺序中按*按Modify_at desc选择

架构

...
"modified_at"   "TimestampType" "regular"
"record_end_date"   "TimestampType" "regular"
"record_entity_type"    "UTF8Type"  "clustering_key"
"record_frequency"  "UTF8Type"  "regular"
"record_id" "UUIDType"  "partition_key"

1 个答案:

答案 0 :(得分:2)

首先,ORDER BY在Cassandra中确实是多余的。它只能在分区的 分区中的群集列上操作,然后只能对群集列的确切顺序进行操作。这样做的原因是,Cassandra从磁盘上顺序读取数据,因此它首先按照定义的群集顺序写入所有数据。

因此,IMO,Cassandra中的ORDER BY毫无用处,除非您要更改排序方向(升/降)。

第二,由于其分布式特性,您需要采用面向查询的方法进行数据建模。换句话说,您的表必须设计为支持您打算运行的查询。现在您可以找到解决此问题的方法,但是基本上您是在分布式集群上进行全表扫描,这对任何人来说都不会很好。

因此,建议的解决方法是建立一个像这样的表:

CREATE TABLE stackoverflow.report_summary_by_month (
    record_id uuid,
    record_entity_type text,
    modified_at timestamp,
    month_bucket bigint,
    record_end_date timestamp,
    record_frequency text,
    PRIMARY KEY (month_bucket, modified_at, record_id)
) WITH CLUSTERING ORDER BY (modified_at DESC, record_id ASC);

然后,此查询将起作用:

SELECT * FROM report_summary_by_month
WHERE month_bucket = 201904 
AND modified_at >= '2019-04-23' AND modified_at < '2019-04-26';

这里的想法是,当您关心结果的顺序时,您需要按其他方式进行划分,以便进行排序。在此示例中,我选择了month,因此我将您的结果按月“存储”到了名为month_bucket的分区键中。在每个月的时间里,我都以modified_at结尾的顺序聚集在DESC上。这样,最近的结果位于分区的“顶部”。然后,我投入record_id作为平局键以帮助确保唯一性。

如果您仍然专注于以错误的方式执行此操作:

您实际上可以在当前架构上运行范围查询。但是,由于跨多个节点的“亿万条记录”,我对此寄予厚望。但是您可以使用ALLOW FILTERING指令(您永远不要真正使用它)来实现它。

SELECT * FROM report_summary
WHERE modified_at >= '2019-04-23'
AND modified_at < '2019-04-26' ALLOW FILTERING;

此方法有以下警告:

  • 在许多节点上有很多记录,它可能会超时。
  • 如果无法为该查询标识单个分区,则会选择一个协调器节点,并且该节点极有可能过载。
  • 由于这是从多个分区中提取行,因此无法强制执行排序顺序。
  • ALLOW FILTERING使Cassandra的工作方式并非真正设计出来的,所以我永远不会在生产系统上使用它。

如果您确实需要运行这样的查询,建议您使用内存聚合工具,例如Spark。

另外,由于最初的问题是关于ORDER BY的,所以我不久前写了一篇文章,更好地解释了这个主题:https://www.datastax.com/dev/blog/we-shall-have-order