【问题标题】:cassandra primary key column cannot be restrictedcassandra主键列不能被限制
【发布时间】:2015-04-18 09:11:45
【问题描述】:

我第一次在 Web 应用程序中使用 Cassandra,但遇到了查询问题。 这是我的标签:

CREATE TABLE vote (
    doodle_id uuid,
    user_id uuid,
    schedule_id uuid,
    vote int,
    PRIMARY KEY ((doodle_id), user_id, schedule_id)
);

在每个请求中,我都会指明我的分区键 doodle_id。 例如,我可以毫无问题地制作:

select * from vote where doodle_id = c4778a27-f2ca-4c96-8669-15dcbd5d34a7 and user_id = 97a7378a-e1bb-4586-ada1-177016405142;

但在我提出的最后一个请求中:

select * from vote where doodle_id = c4778a27-f2ca-4c96-8669-15dcbd5d34a7 and schedule_id = c37df0ad-f61d-463e-bdcc-a97586bea633;

我收到以下错误:

Bad Request: PRIMARY KEY column "schedule_id" cannot be restricted (preceding column "user_id" is either not restricted or by a non-EQ relation)

我是 Cassandra 的新手,但如果我错了,请纠正我,在复合主键中,第一部分是 PARTITION KEY,它是强制允许 Cassandra 知道在哪里查找数据的。 然后其他部分是 CLUSTERING KEY 对数据进行排序。

但我仍然不明白为什么我的第一个请求有效,而第二个无效?

如果有人能提供帮助,那将是非常高兴的。

【问题讨论】:

    标签: cassandra cql cqlsh


    【解决方案1】:

    在 Cassandra 中,您应该设计适合您查询的数据模型。因此,支持您的第二个查询(doodle_idschedule_id 的查询,但不一定是 user_id 的查询)的正确方法是创建一个新表来处理该特定查询。此表几乎相同,只是 PRIMARY KEY 会略有不同:

    CREATE TABLE votebydoodleandschedule (
        doodle_id uuid,
        user_id uuid,
        schedule_id uuid,
        vote int,
        PRIMARY KEY ((doodle_id), schedule_id, user_id)
    );
    

    现在这个查询可以工作了:

    SELECT * FROM votebydoodleandschedule 
    WHERE doodle_id = c4778a27-f2ca-4c96-8669-15dcbd5d34a7 
    AND schedule_id = c37df0ad-f61d-463e-bdcc-a97586bea633;
    

    这使您不必指定ALLOW FILTERING。依赖ALLOW FILTERING 绝不是一个好主意,当然也不应该在生产集群中做。

    【讨论】:

    • 非常感谢您的两个回答!我现在更好地理解了 Cassandra 的工作原理。所以我创建了一个你提到的新表来处理我的查询,现在它工作正常。
    • 如果我想在 doodleid 中执行 > 和
    • @ParthTrivedi 要对doodle_id 执行范围查询,您需要创建一个具有不同分区键的新表(找出对您的数据有意义的内容)。然后您可以查询doodle_id 的范围以获取特定的分区键。
    • @Aaron 你能解释一下为什么第二个查询不起作用吗?是因为 Cassandra 中有一些内部数据存储吗?我可以在某处读到它。提前致谢。
    • @pWoz Cassandra 在可以从磁盘读取连续数据流并且集群键确定磁盘排序顺序时效果最佳。因此,可以只过滤第一个或几个,但不能跳过它们,因为这需要从磁盘随机读取。一个很好的资源是 Patrick McFadin 关于构建主键的帖子:planetcassandra.org/blog/…
    【解决方案2】:

    集群键还用于查找给定分区内的列。使用您的模型,您将能够通过以下方式查询:

    • doodle_id
    • doodle_id/user_id
    • doodle_id/user_id/schedule_id
    • user_id 使用ALLOW FILTERING
    • user_id/schedule_id 使用ALLOW FILTERING

    您可以将主键视为文件路径 doodle_id#123/user_id#456/schedule_id#789,其中所有数据都存储在最深的文件夹中(即 schedule_id#789)。当您查询时,您必须指明您开始搜索的子文件夹/子树。

    由于分区内列的组织方式,您的第二个查询不起作用。 Cassandra 无法在分区中获得连续 slice 列,因为它们是交错的。

    您应该反转主键顺序(doodle_id、schedule_id、user_id)才能运行您的查询。

    【讨论】:

    • 允许过滤仅用于开发或调试目的,您扫描表中的所有数据。我使用允许过滤破坏了我的生产环境.. docs.datastax.com/en/cql-oss/3.3/cql/cql_reference/…
    • ALLOW FILTERING 不一定只是为了开发:'如果你“知道你在做什么”,你可以强制执行' - docs.scylladb.com/getting-started/dml/#allowing-filtering 。他们担心当您实际上只希望快速返回 1 或 2 个特定行时,您可能会意外触发从每个节点加载每一行。听起来 ALLOW-FILTERING 将使用尽可能多的主键(“主键前缀” - 没有丢失任何部分)。但以上行缺少分区键 (doodle_id),因此将全面扫描每一行。
    猜你喜欢
    • 2020-11-27
    • 2015-01-30
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2020-01-13
    • 2017-05-24
    • 1970-01-01
    • 2017-12-04
    相关资源
    最近更新 更多