Skip to main content
 首页 » 编程设计

python之Cassandra 查询制作之无法执行此查询,因为它可能涉及数据过滤,因此可能具有不可预测的性能

2025年05月04日12duanxz

我想要以下 Cassandra 模型:-

class Automobile(Model): 
    manufacturer = columns.Text(primary_key=True) 
    year = columns.Integer(index=True) 
    model = columns.Text(index=True) 
    price = columns.Decimal(index=True) 

我需要以下查询:-

q = Automobile.objects.filter(manufacturer='Tesla') 
q = Automobile.objects.filter(year='something') 
q = Automobile.objects.filter(model='something') 
q = Automobile.objects.filter(price='something') 

这些都工作正常,直到我想要多列过滤,即当我尝试时

q = Automobile.objects.filter(manufacturer='Tesla',year='2013') 

它会抛出一个错误,指出无法执行此查询,因为它可能涉及数据过滤,因此可能具有不可预测的性能。

我用 allowed_filtering 重写了查询,但这不是最佳解决方案。

然后在阅读更多内容后,我按如下方式编辑了我的模型:-

class Automobile(Model): 
    manufacturer = columns.Text(primary_key=True) 
    year = columns.Integer(primary_key=True) 
    model = columns.Text(primary_key=True) 
    price = columns.Decimal() 

有了这个,我也能够在没有任何警告的情况下过滤多个 Coulms。

当我执行 DESCRIBE TABLE automobile 时,它显示这创建了复合键 PRIMARY KEY ((manufacturer), year, model)。

那么,我的问题是,如果我将每个属性都声明为主键会怎样?这有什么问题吗,因为我也可以过滤多个列。

这只是一个小模型。如果我有一个模型,比如:-

class UserProfile(Model): 
    id = columns.UUID(primary_key=True, default=uuid.uuid4) 
    model = columns.Text() 
    msisdn = columns.Text(index=True) 
    gender = columns.Text(index=True) 
    imei1 = columns.Set(columns.Text) 
    circle = columns.Text(index=True) 
    epoch = columns.DateTime(index=True) 
    cellid = columns.Text(index=True) 
    lacid = columns.Text(index=True) 
    mcc = columns.Text(index=True) 
    mnc = columns.Text(index=True) 
    installed_apps = columns.Set(columns.Text) 
    otp = columns.Text(index=True) 
    regtype = columns.Text(index=True) 
    ctype = columns.Text(index=True) 
    operator = columns.Text(index=True) 
    dob = columns.DateTime(index=True) 
    jsonver = columns.Text(index=True) 

如果我将每个属性都声明为 PK,这有什么问题吗?

请您参考如下方法:

要理解这一点,您需要了解 cassandra 如何存储数据。主键中的第一个键称为分区键。它定义行所属的分区。分区中的所有行存储在一起,并一起复制。在分区内,行根据聚簇键存储。这些是 PK 中不是分区键的列。因此,如果您的 PK 是 (a, b, c, d),则 a 定义分区。在特定分区(例如,a = a1)中,行按 b 排序存储。对于每个 b,行按 c 排序存储...等等。查询时,您会命中一个(或几个分区),然后需要指定每个连续的集群键,直到您要查找的键为止。除了查询中指定的最后一个聚类列外,它们必须完全相等,这可能是一个范围查询。

在前面的例子中,你可以这样做

其中 a = a1 和 b > b1 其中 a = a1 且 b=b1 且 c>c1 其中 a = a1 且 b=b1 且 c=c1 且 d > d1

但不能这样做:

其中 a=a1 和 c=c1

要做到这一点,您需要“允许过滤”(实际上,您应该考虑更改您的模型,或者此时进行非规范化)。

现在,关于将每一列都作为 PK 的一部分的问题。你可以这样做,但请记住,Cassandra 中的所有写入都是更新插入。行由它们的主键标识。如果您将每一列都作为 PK 的一部分,您将无法编辑一行。不允许更新主键中任何列的值。