【问题标题】:Query Cassandra with Both Primary Key and Secondary Key Constraints使用主键和辅助键约束查询 Cassandra
【发布时间】:2015-06-23 07:44:19
【问题描述】:

我在 Cassandra 中有一个表定义为

CREATE TABLE foo ("A" text, "B" text, "C" text,
    "D" text, "E" text, "F" text,
    PRMIARY KEY ("A", "B"),
    INDEX ("C"))

我在这张表中插入了数十亿条记录。现在我想用 CQL 查询表

SELECT * FROM foo WHERE "A"='abc' AND "B"='def' AND "C"='ghi'

我不断收到 1200 错误提示

ReadTimeout: code=1200 [Coordinator 节点等待副本超时 节点的响应] message="操作超时 - 仅收到 0 响应。” info={'received_responses': 0, 'required_responses': 1, “一致性”:“一个”}

谷歌搜索后,我怀疑这个错误的原因是查询被定向到一些不包含任何数据的分区。

我的问题是

  1. 是否有任何约束查询同时指定主键和辅助键的CQL?
  2. 如果我在我的 CQL 中指定了分区键,此处为“A”='abc'(如果错误请纠正我),为什么 C* 仍会尝试其他显然不保存数据的分区?
  3. 有解决此超时问题的提示吗?

谢谢!

【问题讨论】:

    标签: cassandra cql cql3


    【解决方案1】:

    注意:对于我的示例,我去掉了列名周围的双引号。除了在列名(而不是值)中保留大小写之外,它实际上并没有做任何事情,只是为了搞砸工作。

    是否有任何约束查询同时指定主键和辅助键的CQL?

    首先,我需要弄清楚你的“主键”和“辅助键”到底是什么。如果您将C 称为“辅助键”,那么“是”可以,但有一些限制。如果您的意思是您的 partition 密钥 (A) 和您的 cluster 密钥 (B),那么可以。

    通过您的分区键和集群键(甚至您的分区键)进行查询:

    aploetz@cqlsh:stackoverflow2> SELECT * FROM foo WHERe A='abc' AND B='def';
    
     a   | b   | c   | d   | e   | f
    -----+-----+-----+-----+-----+-----
     abc | def | ghi | jkl | mno | pqr
    
    (1 rows)
    aploetz@cqlsh:stackoverflow2> SELECT * FROM foo WHERe A='abc';
    
     a   | b   | c   | d   | e   | f
    -----+-----+-----+-----+-----+-----
     abc | ddd | ghi | jkl | mno | pqr
     abc | def | ghi | jkl | mno | pqr
    
    (2 rows)
    

    当我创建您的表和索引时,插入几行,然后运行您的查询:

    aploetz@cqlsh:stackoverflow2> SELECT * FROM foo WHERE A='abc' AND B='def' AND C='ghi';
    
     a   | b   | c   | d   | e   | f
    -----+-----+-----+-----+-----+-----
     abc | def | ghi | jkl | mno | pqr
    
    (1 rows)
    

    这行得通。

    如果我在我的 CQL 中指定了分区键,这里是“A”='abc'(如果错误请纠正我),为什么 C* 仍然尝试其他显然不保存数据的分区?

    我认为这不是问题所在。您正在将其限制为单个分区,因此它应该只从abc 分区查询数据。

    我在这张表中插入了数十亿条记录。

    您所看到的是,二级索引的使用被认为是 Cassandra 中的“反模式”的原因。二级索引的工作方式与它们在关系世界中的工作方式不同。它们只是不能很好地扩展到大型集群或数据集。

    有解决这个超时问题的提示吗?

    是的。使用 C 作为第二个集群键重新创建您的表。并且不要C上创建索引。

    CREATE TABLE foo (A text, B text, C text, D text, E text, F text,
      PRMIARY KEY (A, B, C));
    

    重新加载您的数据,然后这应该适合您:

    aploetz@cqlsh:stackoverflow2> SELECT * FROM foo WHERE A='abc' AND B='def' AND C='ghi';
    

    它不仅应该工作,而且不应该超时,而且应该很快。

    【讨论】:

    • 感谢您提供的非常有帮助的答案!我非常感谢你的时间!我会考虑在我们的下一个版本中重新创建表。但是,我可以使用任何设置将超时时间延长到 600 秒吗?正如您所猜到的,我是从关系世界到 C* 的新手。看了你的回答后有点困惑:C*中的分区键+簇键与RDBMS中的主键相同吗,即分区键+簇键唯一标识一条记录,不是吗?
    • 分区+集群=主键。分区键定义了逻辑分区,用于确定哪些物理服务器保存数据。聚类键对每个分区内的剩余记录进行排序。一般来说,提高超时可能是不可取的——您应该能够在超时内查询一页记录。检查 system.log 以确保您确实超时并且没有遇到 TombstoneOverwhelmingException。如果遇到 TOmbstoneOverwhelmingException,则可能是在尝试实现反模式。
    • @JeffJirsa 谢谢!只是为了确认一下,在您的“分区 + 集群 = 主”等式中,它解释为“在 C* 中,分区键和集群键一起作为 RDBMS 中的主键”?超时参数是有道理的。
    • 我知道如果我不指定分区键,二级索引导致查询命中多个节点的问题,但是如果总是提供分区键,为什么二级键使用不扩展?跨度>
    猜你喜欢
    • 1970-01-01
    • 2017-05-22
    • 2015-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多