Почему Cassandra не позволяет запрашивать ключ кластеризации по ограничению IN?

Кто-нибудь знает, почему я не могу использовать запрос, в котором я ограничиваю столбец кластеризации столбцом 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 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* такое ограничение, но ничего не нашел. Также я заглянул в код, но нет никакой информации, почему такая проверка выполняется.

Кто-нибудь знает, в чем причина такого ограничения?


person k0ner    schedule 08.09.2016    source источник


Ответы (2)


Это ограничение основано на том, как типы данных коллекции были «взломаны» в существующем механизме хранения. Коллекция Map реализуется путем хранения каждого ключа в виде уникального имени столбца в той же области, что и столбец кластеризации. Это затрудняет для Cassandra эффективное выполнение операции «IN», особенно для больших коллекций для каждой «строки».

Однако я чувствую, что вы могли бы переработать свою модель данных, чтобы обойти это ограничение и даже не использовать тип коллекции (поскольку с ними связано много проблем, если вы не будете осторожны). Похоже, что «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)
);
person fromanator    schedule 11.09.2016
comment
не могли бы вы подробнее рассказать о same area as the clustering column? - person k0ner; 12.09.2016
comment
Это самое странное ограничение, которое я когда-либо видел в технологии... - person V-Lamp; 09.04.2018

Моя первоначальная мысль заключалась в том, что ограничение связано с влиянием на память и сеть для получения коллекций, поскольку несколько коллекций могут быть возвращены одновременно с ограничением in. Однако я обнаружил, что запрос работает, если он менее ограничен, указав только ключ раздела.

Мои тестовые данные (на 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" }
        ]
      }
    ]
  }
]

Как видите, коллекция на самом деле не отличается от столбца, не являющегося первичным ключом, за исключением агрегации, которая необходима перед ее возвратом клиенту. Интересно, было ли это ограничением для старой реализации бережливости и было ли оно перенесено, хотя нет очевидной причины, по которой это невозможно сделать.

person Ko-Chih Wu    schedule 13.09.2016