Как правильно выбрать ключи раздела, соответствующие индексу - PullRequest
0 голосов
/ 09 января 2019

Я пытаюсь выбрать ключи раздела, которые содержат хотя бы одну строку с определенным значением в индексированном столбце.

При текущем решении все остальные требования выполнены:

  • Возможность выбора отчетов на основе их офиса.
  • Учитывая офис, возможность выбора, используя тип и диапазон дат.
  • Нет необходимости выбирать отчеты по дате без ведома эмиссии и / или типа отчетов.

Наконец, мне нужна возможность выбрать все офисы, в которых определенный пользователь создал отчет. Основываясь на документации cassadra, я добавил индекс для пользовательского столбца.

Таблица определяется как:

create table report(
    office uuid,
    type text,
    insert_date timestamp,
    ...
    created_by uuid,
    ...
    primary key(office, type, insert_date));
create index created_by_idx on report (created_by);

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

create table report2(
    created_by uuid,
    office uuid,
    type text,
    insert_date timestamp,
    ...
    primary key(created_by ,office, type, insert_date));

Я могу успешно выполнить запрос вроде: select office from report where created_by = ? но в результате получается несколько строк с одним и тем же офисным ключом, и это правильно: каждый пользователь может создать несколько отчетов в каждом офисе.

Теперь я фильтрую дублирующиеся офисы на уровне программного обеспечения, но я спрашиваю себя, можно ли отфильтровать эти данные непосредственно во время извлечения.

Я пытался: select distinct office from report where created_by = ? что приводит к SELECT DISTINCT with WHERE clause only supports restriction by partition key and/or static columns.

Тогда я попробовал: select office from report where created_by = ? group by office которые дают мне правильные результаты, но предупреждают: Aggregation query used without partition key

Может ли это быть проблемой? Как справиться с подобным запросом и можно ли игнорировать это предупреждение в этом случае? И, наконец, действительно лучший выбор - использовать такой запрос против select * ... с тем же пунктом where?

1 Ответ

0 голосов
/ 10 января 2019

Существует причина, по которой Cassandra не поддерживает описанную вами функцию, потому что она может быть неэффективной:

Во-первых, вторичный индекс должен действительно перечислять, как вы заметили, все соответствующие ключи строки, а не только отдельные соответствующие ключи раздела. Это потому, что вы можете запросить все строки, а не только отдельные ключи раздела, поэтому данные должны быть там. Другая причина, по которой эти данные должны храниться в индексе, заключается в том, что каждая отдельная строка может быть удалена (или просрочена) по отдельности, поэтому Cassandra необходимо отслеживать все их, чтобы решить, существует ли общий раздел или нет.

Теперь, поскольку у нас уже есть ключи всех строк, перечисленных в списке результатов поиска, вывод только «отдельных» ключей раздела является неэффективной операцией ... Если у вас есть миллион совпадающих строк в одном разделе, Cassandra потребуется сканировать их все, прежде чем выводить только один результат. Кассандра обычно не позволяет пользователю выстрелить себе в ногу с неэффективной операцией (например, посмотрите, как «РАЗРЕШИТЬ ФИЛЬТРАЦИЮ» необходимо явно разрешить неэффективную фильтрацию в запросах SELECT).

При этом имеет смысл, что в будущей версии Cassandra будет разрешен запрошенный вами запрос "SELECT DISTINCT", возможно, требующий от пользователя сказать "ALLOW FILTERING", чтобы подтвердить, что он может быть медленным. Кроме того, альтернативная реализация может включать медленные обновления (каждое обновление строки будет проверять жизнеспособность раздела), а затем быстрое чтение. Сцилла рассмотрел такую ​​реализацию, но также не реализовал ее (см. https://github.com/scylladb/scylla/issues/3435).

...