如何在Cassandra中统计指定日期的distinct id数量?
解决Cassandra统计单日distinct id的问题
我来帮你搞定这个Cassandra查询的难题~首先得先说说你原来的SQL写法在Cassandra里行不通的几个原因:
- timestamp类型不能用LIKE模糊匹配:你的
dt是timestamp类型,Cassandra不支持对非字符串类型用LIKE,得用时间范围的比较运算符(>=/<=)来限定日期。 - 主键结构导致的查询效率问题:你的表分区键是
(id,dt),如果查询时不指定id,会触发全表扫描——这在Cassandra里数据量大的时候性能会非常差,甚至可能超时。 - COUNT(DISTINCT)的用法限制:Cassandra的
COUNT(DISTINCT)虽然支持,但在无分区限定的全表扫描场景下,性能表现会很糟糕。
方案一:直接查询(适合小数据集,临时需求)
如果你暂时没法改表结构,那可以用时间范围来替代LIKE,写出能运行的CQL:
SELECT COUNT(DISTINCT id) FROM OrderHistory WHERE dt >= '2018-10-01 00:00:00' AND dt <= '2018-10-01 23:59:59';
⚠️ 注意:这个查询会遍历所有分区,数据量大的话别轻易用,大概率会慢到超时。
方案二:优化表结构(推荐,适合长期需求)
既然你经常需要按日期统计distinct id,那最好调整表的分区策略,把日期维度加入分区键,让查询可以精准定位到目标分区:
方法1:新建优化后的表
CREATE TABLE IF NOT EXISTS OrderHistoryByDay ( status varchar, id bigint, ordtype varchar, side varchar, instrument varchar, exrate double, dt timestamp, day date, -- 新增日期字段,按天分区 PRIMARY KEY ((day), id, status, dt) );
插入数据时,把day字段设为dt对应的日期(比如用dateOf(dt)函数自动生成),之后查询就快多了:
SELECT COUNT(DISTINCT id) FROM OrderHistoryByDay WHERE day = '2018-10-01';
方法2:创建物化视图(不用改原表)
如果不想动原表,可以创建一个物化视图来适配按日查询的需求:
CREATE MATERIALIZED VIEW OrderHistoryByDay AS SELECT id, status, dt, ordtype, side, instrument, exrate FROM OrderHistory WHERE id IS NOT NULL AND dt IS NOT NULL AND status IS NOT NULL -- 主键字段不能为null PRIMARY KEY ((dateOf(dt)), id, status, dt);
然后用物化视图查询:
SELECT COUNT(DISTINCT id) FROM OrderHistoryByDay WHERE dateOf(dt) = '2018-10-01';
总结
Cassandra是写优化的数据库,查询要尽量贴合分区键设计。如果长期有按日统计的需求,优先用方案二的结构优化,能避免全表扫描带来的性能问题;临时小数据查询可以用方案一应急。
内容的提问来源于stack exchange,提问作者Maks Jok
相关产品推荐
相关产品推荐

