Что касается документации Cassandra (неаккуратной, все еще сбивающей с толку) по ключам, разделам

#cassandra

#cassandra

Вопрос:

У меня есть таблица с высокой скоростью записи, которую я переношу с Oracle на Cassandra. В Oracle PK — это a (int: ClientID, id: UUID). Существует около 10 миллиардов строк. Сразу же я сталкиваюсь с этим бессмысленным предупреждением:

https://docs.datastax.com/en/cql/3.3/cql/cql_using/useWhenIndex.html : «Если вы создадите индекс для столбца с высокой мощностью, который имеет много разных значений, запрос между полями приведет к многочисленным поискам с очень небольшим количеством результатов. В таблице с миллиардом песен поиск песен по автору (значение, которое обычно уникально для каждой песни) вместо их исполнителя, вероятно, будет очень неэффективным. Вероятно, было бы более эффективно вручную поддерживать таблицу в виде индекса вместо использования встроенного индекса Cassandra. «

Похоже, что это не только не позволяет эффективно находить с помощью PK, но и не определяет, что означает «запрос между полями» и в чем разница между встроенным индексом, вторичным индексом и подфразами primary_key clustering в команде create table. Ненужное описание. Это 2019 год. Разве это не должно быть исправлено к настоящему времени?

AFAIK, это все равно вводит в заблуждение:

 CREATE TABLE dev.record (
clientid int,
id uuid,
version int,
payload text,
PRIMARY KEY (clientid, id, version)
) WITH CLUSTERING ORDER BY (id ASC, version DESC)

insert into record (id,version,clientid,payload) values
(d5ca94dd-1001-4c51-9854-554256a5b9f9,3,1001,'');
insert into record (id,version,clientid,payload) values
(d5ca94dd-1002-4c51-9854-554256a5b9e5,0,1002,'');
  

Токен в clientid действительно показывает, что они находятся в разных разделах, как и ожидалось.

Переходя к главному пункту. Если кто-то искал одну строку с учетом идентификатора клиента и UUID — И— Cassandra позволила вам пропустить указание идентификатора клиента, чтобы он не знал, какие узлы искать, тогда убедитесь, что поиск может быть медленным. Но это не:

 select * from record where id=
  d5ca94dd-1002-4c51-9854-554256a5b9e5;
InvalidRequest: ... despite the performance unpredictability,
use ALLOW FILTERING"
  

И то же самое с другими вариантами, которые исключают clientid. Итак, не следует ли нам заключить, что Cassandra отлично справляется с поиском по таблицам с высокой мощностью, которые возвращают «очень мало результатов»?

Комментарии:

1. Вопреки тому, что, по-видимому, подразумевает документация — или не подразумевает, потому что она так плохо написана — этот выбор очень эффективен : выберите * из dev.record, где ClientID= 1001 и id = 5bcd …ff и version = 0, просто отлично. Если вы попробуете выбрать без ClientID, вас предупредят, что вам нужно предложение фильтрации, и результат может быть медленным. Таким образом, вы даже не можете случайно попасть в неверный запрос

Ответ №1:

Все, что требует чтения всего контекста базы данных, не будет работать, как в случае со сканированием, id поскольку любой из ваших clientid ключей раздела может содержать его. Просмотр потенциально тысяч sstables на хост и просмотр каждого раздела каждого из них для проверки не сработает. Если у вас возникли трудности с моделью данных и вы не совсем понимаете разницу между ключами разделов и ключами кластеризации, я бы порекомендовал вам ознакомиться с некоторыми вводными классами (например, datastax academy), видеороликами YouTube или книгой и т.д., Прежде чем разрабатывать свою схему. Это не реляционная база данных, и проектирование вокруг ваших данных вместо ваших запросов доставит вам неприятности. При переходе с oracle вы должны не просто копировать свои таблицы и перемещать данные, иначе это также не будет работать.

Ключ кластеризации — это порядок, в котором данные для раздела упорядочены на диске, что называется «встроенным индексом». Каждая sstable имеет компонент index, который содержит расположения ключей разделов для этой sstable. Это также включает в себя индекс ключей кластеризации для каждого раздела каждые 64 КБ (по крайней мере, по умолчанию), по которым можно выполнять поиск. Ключи кластеризации, которые существуют между каждой из этих индексированных точек, неизвестны, поэтому все они должны быть проверены. Давным-давно также сохранялся фильтр bloom для ключей кластеризации, но это был такой редкий случай использования, когда это помогло снизить накладные расходы, что он был удален в версии 2.0.

Вторичные индексы трудно хорошо масштабировать, отсюда и предупреждение о мощности, я бы настоятельно рекомендовал просто денормализовать данные и не использовать индекс в любой форме, поскольку использование запросов с большим разбросом по распределенной системе приведет к проблемам с доступностью и производительностью. Если вам это действительно нужно, ознакомьтесьhttp://www.doanduyhai.com/blog/?p=13191 попытаться получить правильные данные (на мой взгляд, не стоит).

Комментарии:

1. Я работаю с Oracle более 25 лет и начал работать с Cassandra последние 3 года. Я многому научился в отношении сходств и различий (и их много). Если у вас есть вопросы, вы можете связаться со мной в автономном режиме для обсуждения. Индексы Cassandra — это не более чем таблицы под ним, откуда и берется запутанная часть. Это не объект b-tree, который был бы эффективным, и, следовательно, его сложнее понять, если вы думаете в этих терминах.

2. @Chris — ну, спасибо, что нашли время ответить. Но вы не ответили на вопрос. Вы пишете «… сканирование по идентификатору, поскольку любой из ключей вашего раздела clientid может содержать его». PK — это (clientid, id, version), например, разделенный по ClientID на узел, а затем (id, version) точно именующий строку. Более того, я не получил никакого отклика на тот факт, что select это не позволяет вам попадать в плохие запросы без явного добавления фильтрации в любом случае. итак, мой вопрос в конце сообщения остается без ответа. Документация отстой.

3. ключ раздела является clientid ключом кластеризации (id, version) . Если не указано, первая часть первичного ключа неявно является ключом раздела — например, ((clientid), id, version) Ключ раздела используется для разделения данных и, по существу, распределяется случайным образом. Итак, вам нужно проверить каждый узел и каждый раздел в кластере, чтобы найти любое значение одного id . Она не может (и не должна) этого делать — даже если вы можете принудительно использовать фильтрацию.