考虑一个具有以下结构的表:
CREATE TABLE statistics (name text, when timestamp, value int,
PRIMARY KEY ((name, when)));
例如,按名称计算50%值百分比的最佳方法是什么?我想了想:
a) 编写自定义聚合函数+查询,如:
SELECT PERCENTILE(value, 0.5) FROM statistics WHERE name = '...'
b) 先按名称计算元素
SELECT COUNT(value) FROM statistics WHERE name = '...'
然后在按值升序排序时,用分页查找第(0.5/count)行值。比方说,如果计数是100,它将是第50行。
c) 你的想法
我不确定案例a是否能处理这项任务。当行数为奇数时,情况b可能很棘手。
1条答案
按热度按时间41zrol4v1#
只要你一直提供
name
-如果不指定分区并将所有内容都包含在一个分区中,则此请求可能会非常昂贵。我想你是说((name), when)
不是((name, when))
在您的表中,否则您的要求是不可能没有完整的表扫描(使用hadoop或spark)。uda是可行的,但它可能是昂贵的,除非你愿意接受一个近似值。为了让它完全准确,你需要做2次传球(即做一次计数,比第2次传球进入x组,但由于没有隔离,这也不会是完美的)。所以,如果你需要它的精确性,你最好的办法可能就是把整个
statistics[name]
本地分区或让uda在计算之前在Map中建立整个集合(或多数)(如果分区太大,则不建议这样做)。即:如果你愿意接受一个近似值,你可以使用一个采样库,假设你存储了1024个元素,当你的uda得到元素时,你就用一个递减的概率替换其中的元素(vitter的算法r)这是非常容易实现的,如果你的数据集被期望有一个正态分布,它将给你一个不错的近似值。如果您的数据集不是正态分布,这可能会非常遥远。对于正态分布,实际上还有很多其他的选择,但我认为在uda中r是最容易实现的。比如:
在上面的例子中,百分位函数会更快地变慢,玩采样器的大小可以给你或多或少的准确性,但太大,你开始影响性能。通常一个uda的值超过10k(甚至是像
count
)开始失败。同样重要的是要认识到,在这些场景中,虽然单个查询返回单个值,但要获得它需要大量的工作。因此,大量的查询或大量的并发将给您的协调员带来很大的压力。对于cassandra-10783,这确实需要>3.8(我建议使用3.11.latest+)注意:我没有承诺我没有错过示例udas中的off by 1错误-我没有完全测试,但是应该足够接近,您可以从那里开始工作