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