Поскольку 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 году, и в ней я демонстрирую использование этих методов моделирования. Это все еще довольно актуально четыре года спустя (особенно для таких проблем):
Заказ будет!
Прочитайте и посмотрите, поможет ли это.