Производительность Cassandra в кластерной сортировке столбцов против вторичного индекса

Моя схема такая:

A)

CREATE TABLE friend_list (
    userId uuid,
    friendId uuid,
    accepted boolean, 
    ts_accepted timestamp,
    PRIMARY KEY ((userId) ,accepted, ts_accepted)
   ) with clustering order by (accepted desc, ts_accepted desc);

B)

CREATE TABLE friend_list (
        userId uuid,
        friendId uuid,
        accepted boolean, 
        ts_accepted timestamp,
        PRIMARY KEY (userId , ts_accepted)
       ) with clustering order by (ts_accepted desc);
CREATE INDEX ON friend_list (accepted);

Что даст лучшую производительность для запроса:

SELECT * FROM friend_list WHERE userId="---" AND accepted=true;

Насколько я понимаю, Cassandra автоматически сортирует кластерные столбцы в порядке ASC, и мы указываем DESC, если нам нужно изменить порядок сортировки по умолчанию для эффективных запросов.

С моей схемой A я делаю "принятым" как кластеризованный ключ, но мне нужно его отсортировать без необходимости, поскольку мне определенно нужно отсортировать "ts_accepted" в DESC. Повлияет ли эта нежелательная сортировка "принятых" на производительность?

Если это так, скажите, что я делаю "принятым" в качестве вторичного индекса в схеме B. Я знаю, что вторичный индекс неплох для низких кардинальных значений (логическое значение). Но все же запрос может иметь проблемы с производительностью.

Пожалуйста, дайте мне знать эффективный способ выполнения этого запроса.

2 ответа

Решение

Я бы пошел за А.

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

Стоимость порядка кластеризации, которой вы боитесь, не подходит. Cassandra хранит кластеризованные столбцы, отсортированные в любом случае...ASC или DESC ничего не меняет. Вы используете немного больше места, но для своего запроса вы хотите нажать "принято", так что это оправдано. Я предполагаю, что ts_accepted нужен по какой-то другой причине? Единственный улов здесь заключается в том, что если вам нужно или у вас есть доступ к ts_accepted в вашем запросе, вам нужно предоставить принятый фильтр равенства. Производительность мудрая, я не вижу проблемы.

Что касается B, индексы для столбцов с чрезвычайно низкой кардинальностью (например, bools) плохие. Подумайте, как хранятся данные - для каждого узла Cassandra поддерживает таблицу, где ключом является значение (true / false), а значения являются ключами всех данных для этого узла, который соответствует ключу. Это может быть очень широким столбцом. Вы бы сделали это, если бы вы моделировали отдельную таблицу? И ты не должен делать это с индексом тоже.

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

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

Наконец, вы нажимаете клавишу раздела (UserId) для вашего запроса. Это очень хорошо для вашего запроса. Это означает, что он попадет ровно в один раздел. В зависимости от вашего варианта использования (и размера записей) может оказаться целесообразным даже загрузить весь раздел и отфильтровать сторону клиента / приложения. Конечно, это зависит от ожидаемых размеров списка друзей, а также от размера данных в зависимости от сетевого трафика и обработки приложений, которые вы хотите / хотите сделать. Например, загрузка 100 записей и фильтрация для принятой стороны приложения, а также загрузка 50 записей путем фильтрации стороны базы данных могут иметь аналогичные показатели производительности.

Что даст лучшую производительность для запроса: SELECT * FROM friend_list WHERE userId="---" AND accept =true;

Схема (A) даст вам лучшую производительность запросов.

Мне нужно сортировать это без необходимости, поскольку я определенно должен сортировать 'ts_accepted' в DESC

если порядок результатов, который сначала сортируется по "принятым", не влияет на логику кода (порядок записи правильный, то нет необходимости создавать индекс)

Проблема со схемой (B)

создание индекса сверх принятого создаст скрытое семейство столбцов со схемой, подобной

CREATE TABLE friend_list_accept_idx (
        accepted boolean,
        userId uuid, 
        ts_accepted timestamp,
        PRIMARY KEY (accepted),userId , ts_accepted)
       );

что излишне накладные расходы для вас, чтобы поддерживать. И всегда хорошо избегать использования индексов в Кассандре.

Другие вопросы по тегам