比如求每个客户的“平均购买力”。 我们表设计 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 ![]() olap 的数据库都不太支持更新 会影响性能 |
7 leiuu 2021-0-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 、自动折叠,据看官方文档的了解只是为了节省空间。 不知道我的理解是否正确。 |