按复合分区键的单个组件排队时 Cassandra 排队是否更高效?

问题描述 投票:0回答:1

我在 Cassandra 中遇到问题,我想通过具有高基数的列查询数据。现在,为了拥有更平衡的数据库,需要以分区大小更相等的方式选择分区键。但对我来说,一方面能够通过具有高基数的列进行查询,另一方面能够在分区之间有效地存储数据是很有价值的。

让我们考虑一下我想要存储股票价格警报的场景。我有这张桌子:

CREATE TABLE drop_price_alarm (
        userId bigint,
        symbol text,
        price decimal,
        PRIMARY KEY ((symbol, userId), price)
        );

在我的理解中,我将能够有效地查询所有股票价格大于某个值的记录,并且将 (symbol, userId) 作为复合分区键将确保记录在分区之间合理分布。由于像苹果这样的热门股票会有更多记录,而且我仍然保留了价格的订单,因此 Cassandra 将能够轻松检索所有大于某个股票价格的警报。

当我在 Java 中运行这个时,问题就出现了;我收到此错误:

Caused by: org.springframework.data.cassandra.CassandraInvalidQueryException: Query; CQL [SELECT * FROM droppricealarm WHERE symbol=? AND price<=?]; Cannot execute this query as it might involve data filtering and thus may have unpredictable performance. If you want to execute this query despite the performance unpredictability, use ALLOW FILTERING

这是我的桌子:

@Table
public class DropPriceAlarm {

    @PrimaryKeyColumn(
            name = "symbol", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
    private String symbol;
    @PrimaryKeyColumn(
            name = "userId", ordinal = 2, type = PrimaryKeyType.PARTITIONED)
    private long userId;


    @PrimaryKeyColumn(
            name = "price", ordinal = 1, type = PrimaryKeyType.CLUSTERED)
    private BigDecimal price;

    public DropPriceAlarm(String symbol, long userId, BigDecimal price) {
        this.symbol = symbol;
        this.userId = userId;
        this.price = price;
    }

    public long getUserId() {
        return userId;
    }

    public void setUserId(long userId) {
        this.userId = userId;
    }

    public String getSymbol() {
        return symbol;
    }

    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

}

这是我的存储库:

    List<DropPriceAlarm> findBySymbolAndUserIdAndPriceLessThanEqual(String symbol, long userId, BigDecimal price);
}

为什么我会收到此错误,我的推理有什么不正确的地方?

spring-boot cassandra
1个回答
0
投票

问题在于查询中未包含分区键。分区机制确实基于一致性哈希机制(默认为 murmur3)将数据分发到节点。

要检索数据,默认情况下您应该提供分区键,因为这是知道从哪里获取数据所必需的。

示例中基于价格的聚类顺序,仅是分区内的订单,它不是任何类型的全局排序顺序。

如果您希望根据价格检索数据,您有三个选择:

  • 使用 SAI 索引(C* 5.0 / Datastax Astra),但这将是一个昂贵的查询,因为它是一个分散收集查询,可以要求每个节点检索数据,然后在协调器上排序。
  • 使用spark-sql将并行查询所有令牌范围并将数据拉到spark以排序,这不会是一个快速/低延迟的操作。
  • 重构数据以匹配查询模式。 (问题中没有足够的有关模式的信息。)
© www.soinside.com 2019 - 2024. All rights reserved.