我这个场景, clickhouse 适用吗?

2021-06-03 11:17:26 +08:00
 wenjun19931112

比如求每个客户的“平均购买力”。 我们表设计 3 个字段 ( userId,orderId,price )。 但是 price 可能会变动,这条记录会被删除(业务原因)。

为了支持 update\delete,我们选择版本折叠树。 主键设置 (userId,orderId)两个字段。 但是我的统计维度却只要 userId (求每个客户的“平均购买力”),如果通过一个维度去聚合 “版本折叠树”,得到的数据又是不准确的。

有什么办法吗?

4368 次点击
所在节点    ClickHouse
15 条回复
leiuu
2021-06-03 11:45:10 +08:00
1. 为什么结果是不准确的 这里没太理解
2. 如果你的描述我理解没错的话 好多 olap 引擎都可以支持这类的聚合统计的 数据不大甚至可以用 mysql (这里可能是我想简单了)
weizhen199
2021-06-03 11:53:48 +08:00
表更新频率数据量?
wenjun19931112
2021-06-03 12:44:09 +08:00
@weizhen199
数据量至少是千万级别,更新频率不算太高
wenjun19931112
2021-06-03 12:44:41 +08:00
@leiuu
因为 版本折叠树 需要 group by 主键,聚合出来的数据才是准确的
liuhuansir
2021-06-03 12:51:18 +08:00
@wenjun19931112 千万级别不需要 clickhouse 吧?我们都是百亿级别的数据,监控类数据,不存在更新
PiersSoCool
2021-06-03 13:09:40 +08:00
olap 的数据库都不太支持更新 会影响性能
leiuu
2021-06-03 13:13:44 +08:00
我试了下结果是符合预期的呢,
```sql
CREATE TABLE user_order_price
(
userId UInt64,
orderId UInt8,
price Float64,
sign Int8,
version UInt8
)
ENGINE = VersionedCollapsingMergeTree(sign, version)
ORDER BY (userId,orderId)



INSERT INTO user_order_price VALUES (101, 10000, 100, 1, 1),(101, 10000, 100, -1, 2),(102, 10000, 200, 1, 2)



INSERT INTO user_order_price VALUES (103, 10000, 500, 1, 2)



SELECT
userId,
sum(price * sign) AS avgPrice
FROM user_order_price
GROUP BY userId

```
结果不准确是指哪个位置
wenjun19931112
2021-06-03 13:31:01 +08:00
@leiuu
sql 中 `group by userId`,但是你的主键是( userId,orderId )。那么 sql 不是按主键对应折叠,`avgPrice`会不对。
数据正确的写法是 `group by userId,orderId`
wenjun19931112
2021-06-03 13:31:55 +08:00
@liuhuansir
考虑到后期的数据增长,数据上亿是很快的。
wenjun19931112
2021-06-03 13:33:28 +08:00
我找到了一个新的写法,搜索之前使用 final 去合并。因为据说现在 final 的性能已经比较好了。
比如:
SELECT
userId,
sum(price * sign) AS avgPrice
FROM user_order_price FINAL
GROUP BY userId

https://cloud.tencent.com/developer/article/1662230
wenjun19931112
2021-06-03 13:34:40 +08:00
wenjun19931112
2021-06-03 13:56:50 +08:00
@leiuu
我想错了,group by 没有说要求一定要是主键
leiuu
2021-06-03 14:09:08 +08:00
👍 查询中使用 final 关键词确实是一个折衷的较好的方法: https://clickhouse.tech/docs/en/sql-reference/statements/select/from/#select-from-final


这里还要正好探讨下:
```
SELECT
userId,
sum(price * sign) AS avgPrice
FROM user_order_price
GROUP BY userId
```
这个 sql 其实和折叠数关系不大,你的场景中 price 都是正数的情况下,结果应该是对的,和是否使用全部主键关系不大,不过这里也可能我理解错误。

另外如果相同 userId 的数据分散在不同物理机上,那结果可能是不对的(未做验证)。
leiuu
2021-06-03 14:10:21 +08:00
对的 对主键没要求的 😂
wenjun19931112
2021-06-03 14:30:21 +08:00
@leiuu
1 、我测试了一下。price 是负数也不影响结果。
2 、我认为和数据分布在不同机器上没关系。假设不考虑自动折叠,我认为用最普通的 mergetree 也能达到我要的效果( update `price`后保证 groupby 的聚合结果正确)。只要我人为的增加一个 sign 列就好了。
3 、自动折叠,据看官方文档的了解只是为了节省空间。
不知道我的理解是否正确。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/781077

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX