Кассандра сортирует результаты по некластерному ключу

Наш сценарий использования Cassandra - показать топ-10 недавних посетителей поста. Ниже приводится определение таблицы Кассандры.

CREATE TABLE blogs_by_visitor (
             blogposturl text,
             visitor text,
             visited_ts timestamp,
             PRIMARY KEY (blogposturl, visitor)
           );

Теперь, чтобы показать топ-10 последних посетителей данного поста в блоге, необходимо указать явное условие "упорядочить по" в метке времени desc. Поскольку visted_ts не является частью столбца кластеризации в Cassandra, мы не можем этого сделать. Причина того, что visit_ts не является частью столбца кластеризации, состоит в том, чтобы избежать записи повторяющихся (читаемых как дубликаты) посетителей. Первичный ключ разработан таким образом, чтобы установить последнюю временную метку для повторного посетителя.

В мире СУБД запрос будет выглядеть следующим образом, и можно создать вторичный индекс со столбцами blogposturl и timestamp.

Select visitor from blog_table
where 
blogposturl = ?
and rownum <= 10
order by timestamp desc

Альтернатива, которая в настоящее время используется в нашем приложении Cassandra, заключается в получении результатов, а затем сортировке на основе метки времени на стороне приложения. Но что, если конкретный блог пост становится настолько популярным, и его посетило более 100000 человек? Запрос становится очень медленным для этих блогов.

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

Есть идеи о том, как мы можем смоделировать таблицу по-другому?

Фактическая таблица имеет дополнительные столбцы, уменьшенные здесь для простоты

1 ответ

Этот тип работы выполняется Apache Spark или Hadoop. Задание по расписанию, которое рассчитывает уникальный порядок посетителей по метке времени для каждого URL и сохраняет результат в кассандре.

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

Давайте создадим материализованное представление:

CREATE MATERIALIZED VIEW unique_visitor AS
    SELECT *
    FROM blogs_by_visitor
    WHERE blogposturl IS NOT NULL AND visitor IS NOT NULL AND visited_ts IS NOT NULL
    PRIMARY KEY (blogposturl, visited_ts, visitor)
    WITH CLUSTERING ORDER BY (visited_ts DESC, visitor ASC);

Теперь вы можете просто выбрать 10 последних уникальных посетителей блога.

SELECT * FROM unique_visitor WHERE blogposturl = ? LIMIT 10;

Вы можете видеть, что я не указал порядок сортировки в запросе выбора. Потому что в материализованной схеме представления указан порядок сортировки по умолчанию visited_ts DESC

Обратите внимание: приведенная выше схема приведет к огромному количеству неожиданного создания надгробий в Материализованных представлениях.

Или Вы можете изменить свой стол schmea, как показано ниже:

CREATE TABLE blogs_by_visitor (
     blogposturl text,
     year int,
     month int,
     day int,
     visitor text,
     visited_ts timestamp,
     PRIMARY KEY ((blogposturl, year, month, day), visitor)
);

Теперь у вас есть только небольшое количество данных в одном разделе. Таким образом, вы можете сортировать всех посетителей на основе visited_ts в этом единственном разделе со стороны клиента. Если вы считаете, что количество посетителей в день может быть огромным, добавьте час к ключу раздела.

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