cassandra - 如何在没有分区键的情况下使用 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"
解决方案
首先,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_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
推荐阅读
- java - 在java中与mysql建立连接时获取java.lang.NullPointerException
- ruby-on-rails - 加载“sqlite3”Active Record 适配器时出错。当我在 Heroku 中部署时
- excel - 如何在 Powerpivot 中显示过去 n 个月?
- javascript - 如何开玩笑地在异步函数中抛出错误
- r - Stickplot 向量不能准确地显示方向
- swift - UINavigationController 后退按钮不会结束 UITextField 编辑
- python - Python 套接字 - 带有 base10 的 int() 的无效文字:
- powershell - 仅将每个字符串的最后一段和字符串数组与 Measure-Object 进行比较,并返回整个字符串
- java - 使用 spring-boot-2.2.1 删除 HATEOAS 链接中的 _embedded
- android - 如何自定义浮动操作按钮形状?