Как спроектировать базу данных NoSQL для выбора порядка данных по отметке времени - PullRequest
4 голосов
/ 29 апреля 2019

Подводя итог, хочу создать архитектуру SMACK (Spark, Mesos, Akka, Cassandra и Kafka). Я хочу сделать точку входа, где я смогу вернуть 50 последних элементов, добавленных в мою БД. Вот моя база данных:

create table fireman
(
    uuid uuid primary key,
    date text,
    heartrate int,
    id text,
    location text,
    ratecommunication int,
    temperature int,
    time timestamp
);

Я пытался запросить это:

SELECT * FROM scala_fireman.fireman WHERE temperature > 0 ORDER BY date LIMIT 5 ALLOW FILTERING ;

Но я получил эту ошибку:

ORDER BY is only supported when the partition key is restricted by an EQ or an IN.

Так что мой вопрос как SELECT получить n последний элемент, который я добавлю?

Я увидел, что могу заказать стол, выполнив следующее:

) WITH CLUSTERING ORDER BY (time DESC);

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

1 Ответ

3 голосов
/ 30 апреля 2019

Поскольку Cassandra требует подхода к моделированию на основе запросов, нам необходимо создать таблицу специально для обработки этого запроса:

SELECT * FROM scala_fireman.fireman 
WHERE temperature > 0 ORDER BY date LIMIT 5 ALLOW FILTERING;

Вы когда-нибудь запрашивали uuid? Если так, то мы можем построить новую таблицу. Если нет, вам потребуется изменить свой первичный ключ, чтобы это работало. Создание единственного PRIMARY KEY для столбца ID серьезно ограничивает гибкость вашего запроса (как вы выяснили).

Это столько POC, сколько я могу, на данный момент я отправил 1 миллион пожарных

Это будет вашим первым препятствием. Кассандра может поддерживать только 2 миллиарда клеток на раздел, и это замедлится задолго до этого. Таким образом, мы хотим ограничить количество событий пожарных на раздел «временным интервалом». В качестве примера я буду использовать month_bucket, но вы должны определить, действительно ли это соответствует вашим бизнес-требованиям.

Далее вы хотите ORDER BY date, поэтому мы будем использовать это в качестве ключа кластеризации. На самом деле, поскольку date является текстовым полем, мы будем использовать time, так как я уверен, что вы не хотите, чтобы результаты возвращались в ASCII-бетическом порядке. Быстрое обучение по предложению ORDER BY состоит в том, что оно совершенно лишнее. Вы можете только применять его в заданном порядке ваших ключей кластеризации. Это никогда не должно быть в запросе.

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

Кроме того, я вижу, что вы делаете открытый запрос диапазона temperature. Обычно это плохая идея (и причина, по которой вам нужно ALLOW FILTERING в исходном запросе). Но внутри раздела, это не должно быть слишком плохо. Пока этот раздел не слишком большой. Об этом мы тоже поговорим.

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

    PRIMARY KEY ((month_bucket),time,temperature,uuid))

Так что, если попробуйте это определение таблицы:

create table fireman_events_by_date_and_temp (
    uuid uuid,
    month_bucket int,
    date text,
    heartrate int,
    id text,
    location text,
    ratecommunication int,
    temperature int,
    time timestamp,
    PRIMARY KEY ((month_bucket),time,temperature,uuid))
    WITH CLUSTERING ORDER BY (time DESC, temperature ASC, uuid ASC);

Теперь, если я загружу некоторые данные и выполню ваш запрос:

> SELECT time,temperature,heartrate,location
  FROM fireman_events_by_date_and_temp
  WHERE month_bucket=201904
  AND temperature > 0
  LIMIT 5
  ALLOW FILTERING;

 time                            | temperature | heartrate | location
---------------------------------+-------------+-----------+----------
 2019-04-30 13:40:03.253000+0000 |         644 |       144 |       SF
 2019-04-30 13:39:51.944000+0000 |         644 |       144 |       SF
 2019-04-30 13:39:39.859000+0000 |         644 |       144 |       SF
 2019-04-30 13:39:30.331000+0000 |         644 |       144 |       SF
 2019-04-30 13:39:15.945000+0000 |         644 |       144 |       NY

(5 rows)

Обычно я бы не рекомендовал использовать ALLOW FILTERING. Но пока вы запрашиваете ключ раздела (month_bucket), все данные должны обслуживаться одним и тем же узлом.

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

Заказ будет!

Прочитайте и посмотрите, поможет ли это.

...