比如求每个客户的“平均购买力”。 我们表设计 3 个字段 ( userId,orderId,price )。 但是 price 可能会变动,这条记录会被删除(业务原因)。
为了支持 update\delete,我们选择版本折叠树。 主键设置 (userId,orderId)两个字段。 但是我的统计维度却只要 userId (求每个客户的“平均购买力”),如果通过一个维度去聚合 “版本折叠树”,得到的数据又是不准确的。
有什么办法吗?
1
leiuu 2021-06-03 11:45:10 +08:00
1. 为什么结果是不准确的 这里没太理解
2. 如果你的描述我理解没错的话 好多 olap 引擎都可以支持这类的聚合统计的 数据不大甚至可以用 mysql (这里可能是我想简单了) |
2
weizhen199 2021-06-03 11:53:48 +08:00 via Android
表更新频率数据量?
|
3
wenjun19931112 OP @weizhen199
数据量至少是千万级别,更新频率不算太高 |
4
wenjun19931112 OP @leiuu
因为 版本折叠树 需要 group by 主键,聚合出来的数据才是准确的 |
5
liuhuansir 2021-06-03 12:51:18 +08:00
@wenjun19931112 千万级别不需要 clickhouse 吧?我们都是百亿级别的数据,监控类数据,不存在更新
|
6
PiersSoCool 2021-06-03 13:09:40 +08:00 2
olap 的数据库都不太支持更新 会影响性能
|
7
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 ``` 结果不准确是指哪个位置 |
8
wenjun19931112 OP @leiuu
sql 中 `group by userId`,但是你的主键是( userId,orderId )。那么 sql 不是按主键对应折叠,`avgPrice`会不对。 数据正确的写法是 `group by userId,orderId` |
9
wenjun19931112 OP @liuhuansir
考虑到后期的数据增长,数据上亿是很快的。 |
10
wenjun19931112 OP 我找到了一个新的写法,搜索之前使用 final 去合并。因为据说现在 final 的性能已经比较好了。
比如: SELECT userId, sum(price * sign) AS avgPrice FROM user_order_price FINAL GROUP BY userId https://cloud.tencent.com/developer/article/1662230 |
11
wenjun19931112 OP |
12
wenjun19931112 OP @leiuu
我想错了,group by 没有说要求一定要是主键 |
13
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 的数据分散在不同物理机上,那结果可能是不对的(未做验证)。 |
14
leiuu 2021-06-03 14:10:21 +08:00
对的 对主键没要求的 😂
|
15
wenjun19931112 OP @leiuu
1 、我测试了一下。price 是负数也不影响结果。 2 、我认为和数据分布在不同机器上没关系。假设不考虑自动折叠,我认为用最普通的 mergetree 也能达到我要的效果( update `price`后保证 groupby 的聚合结果正确)。只要我人为的增加一个 sign 列就好了。 3 、自动折叠,据看官方文档的了解只是为了节省空间。 不知道我的理解是否正确。 |