为什么 Cassandra 不允许通过 IN 限制查询集群键?

Why Cassandra doesn't let to query clustering key by IN restriction?

有谁知道为什么我不能使用通过 IN 限制聚类列和 select 集合列的查询?

让我详细说明一下。假设我有类似于以下的数据模型:

create table inventory (
                sku text,
                class text,
                unit text,
                node text,
                supply map<text, frozen<delta_and_time>>,
                supply_compacted int,
                primary key ((sku, class, unit), node));

当我尝试使用以下 select 语句时:

select sku, class, unit, node, supply_compacted where sku = '0' 
           and class = 'good' and unit = 'each' and node in ('1', '2', '3')

一切都很好。但是当我尝试使用相同的限制 select * 时,我得到了关注 荷兰国际集团错误:

Cannot restrict clustering columns by IN relations when a collection is selected by the query

我试图找出为什么在 C* 中有这样的限制,但我找不到任何东西。我也查看了代码,但没有信息说明为什么要执行这样的检查。

有谁知道这样限制的原因是什么?

这是基于收集数据类型 "hacked" 到现有存储引擎中的方式的限制。 Map 集合是通过将每个键存储为与集群列相同的区域中的唯一列名来实现的。因此,Cassandra 很难有效地执行 "IN" 操作,尤其是对于每个 "row".

的大型集合大小

但是我确实觉得您可以重新设计您的数据模型来绕过这个限制,甚至不使用 Collection 类型(因为如果您不小心的话,它们会有很多相关的问题)。看起来 "supply_compacted" 可能是供应图中总库存的汇总?如果是这样,您可以执行以下操作:

create table inventory (
  sku text,
  class text,
  unit text,
  node text,
  supply_compacted int static, -- stored once, total amount of inventory across all nodes
  supply frozen<delta_and_time>,
  primary key ((sku, class, unit), node)
);

我最初的想法是约束是由于内存和网络影响获取集合,因为在限制下可以一次返回多个集合。但是,我发现如果仅通过指定分区键来减少限制,查询就可以正常工作。

我的测试数据(在 Cassandra 3.7 上):

cqlsh:test> create table mytable(X text, Y text, Z text, mylist list<int>, primary key (X,Y));
cqlsh:test> insert into mytable (X,Y,Z,mylist) values('x','y1','z1',[1,2,3]);
cqlsh:test> insert into mytable (X,Y,Z,mylist) values('x','y2','z2',[4,5,6]);
cqlsh:test> select x,y,z from mytable where x = 'x' and y in ('y1');

 x | y  | z
---+----+----
 x | y1 | z1

(1 rows)
cqlsh:test> select * from mytable where x = 'x' and y in ('y1');
InvalidRequest: Error from server: code=2200 [Invalid query] message="Cannot restrict clustering columns by IN relations when a collection is selected by the query"
cqlsh:test> select * from mytable where x = 'x';

 x | y  | mylist    | z
---+----+-----------+----
 x | y1 | [1, 2, 3] | z1
 x | y2 | [4, 5, 6] | z2

(2 rows)

底层 sstable 转储:

$ sstabledump mb-1-big-Data.db
[
  {
    "partition" : {
      "key" : [ "x" ],
      "position" : 0
    },
    "rows" : [
      {
        "type" : "row",
        "position" : 15,
        "clustering" : [ "y1" ],
        "liveness_info" : { "tstamp" : "2016-09-13T08:14:33.172799Z" },
        "cells" : [
          { "name" : "z", "value" : "z1" },
          { "name" : "mylist", "deletion_info" : { "marked_deleted" : "2016-09-13T08:14:33.172798Z", "local_delete_time" : "2016-09-13T08:14:33Z" } },
          { "name" : "mylist", "path" : [ "1a1a0760-798a-11e6-851a-e3954ecad15b" ], "value" : "1" },
          { "name" : "mylist", "path" : [ "1a1a0761-798a-11e6-851a-e3954ecad15b" ], "value" : "2" },
          { "name" : "mylist", "path" : [ "1a1a0762-798a-11e6-851a-e3954ecad15b" ], "value" : "3" }
        ]
      },
      {
        "type" : "row",
        "position" : 99,
        "clustering" : [ "y2" ],
        "liveness_info" : { "tstamp" : "2016-09-13T08:14:49.772718Z" },
        "cells" : [
          { "name" : "z", "value" : "z2" },
          { "name" : "mylist", "deletion_info" : { "marked_deleted" : "2016-09-13T08:14:49.772717Z", "local_delete_time" : "2016-09-13T08:14:49Z" } },
          { "name" : "mylist", "path" : [ "23fefce0-798a-11e6-851a-e3954ecad15b" ], "value" : "4" },
          { "name" : "mylist", "path" : [ "23fefce1-798a-11e6-851a-e3954ecad15b" ], "value" : "5" },
          { "name" : "mylist", "path" : [ "23fefce2-798a-11e6-851a-e3954ecad15b" ], "value" : "6" }
        ]
      }
    ]
  }
]

如您所见,集合与非主键列并没有真正的不同,只是在将其返回给客户端之前需要进行聚合。我想知道这是否是对旧 thrift 实施的限制,并且即使没有明显的原因无法完成也被保留下来。