首页 > 解决方案 > 如何在没有分区键的情况下使用 ORDER_BY 搜索记录

问题描述

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

我们的生产记录有数亿条记录。使用随机排序来定位目标记录是不可能的。

是否有任何解决方法可以在没有分区键的时间范围内进行搜索?

select * from XXXX.report_summary order by modified_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"

标签: cassandracql

解决方案


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

所以 IMO,ORDER BY在 Cassandra 中是非常没用的,除了你想改变排序方向(升序/降序)的情况。

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

因此,推荐的方法是建立一个这样的表:

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_bucket. 在每个月内,我都会modified_atDESC最后的顺序聚集。这样,最近的结果位于分区的“顶部”。然后,我加入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


推荐阅读