Во-первых, ORDER BY
действительно излишне в Кассандре. Он может работать только с вашими столбцами кластеризации в пределах раздела, и только в точном порядке столбцов кластеризации. Причина этого в том, что Cassandra последовательно читает с диска, поэтому для начала записывает все данные в соответствии с заданным порядком кластеризации.
Так что IMO, ORDER BY
в Кассандре довольно бесполезен, за исключением случаев, когда вы хотите изменить направление сортировки (по возрастанию / по убыванию).
Во-вторых, из-за его распределенной природы, вам необходимо использовать ориентированный на запросы подход к моделированию данных. Другими словами, ваши таблицы должны быть разработаны для поддержки запросов, которые вы намереваетесь выполнить. Теперь вы можете найти способы обойти это, но тогда вы в основном выполняете полное сканирование таблицы в распределенном кластере, которое никому не закончится.
Таким образом, рекомендуемый способ сделать это - создать такую таблицу:
CREATE TABLE stackoverflow.report_summary_by_month (
record_id uuid,
record_entity_type text,
modified_at timestamp,
month_bucket bigint,
record_end_date timestamp,
record_frequency text,
PRIMARY KEY (month_bucket, modified_at, record_id)
) WITH CLUSTERING ORDER BY (modified_at DESC, record_id ASC);
Тогда этот запрос будет работать:
SELECT * FROM report_summary_by_month
WHERE month_bucket = 201904
AND modified_at >= '2019-04-23' AND modified_at < '2019-04-26';
Идея здесь заключается в том, что, поскольку вы заботитесь о порядке результатов, вам нужно разделить что-то еще, чтобы обеспечить возможность сортировки. Для этого примера я выбрал месяц, поэтому я «разбил» ваши результаты по месяцам на ключ раздела под названием month_bucket
. В течение каждого месяца я группирую по окончанию порядка modified_at
в DESC
. Таким образом, самые последние результаты находятся в верхней части раздела. Затем я добавил record_id
в качестве ключа тай-брейка, чтобы обеспечить уникальность.
Если вы все еще сосредоточены на том, чтобы делать это неправильно:
Вы можете фактически выполнить запрос диапазона в вашей текущей схеме. Но с «сотнями миллионов записей» на нескольких узлах у меня нет больших надежд на то, что это сработает. Но вы можете сделать это с помощью директивы ALLOW FILTERING
(которую вы никогда не должны использовать).
SELECT * FROM report_summary
WHERE modified_at >= '2019-04-23'
AND modified_at < '2019-04-26' ALLOW FILTERING;
Этот подход имеет следующие оговорки:
- При большом количестве записей на многих узлах время ожидания может истечь.
- Не имея возможности идентифицировать один раздел для этого запроса, будет выбран узел-координатор, и этот узел с большой вероятностью будет перегружен.
- Поскольку это извлечение строк из нескольких разделов, порядок сортировки не может быть принудительно установлен.
ALLOW FILTERING
заставляет Cassandra работать так, как он на самом деле не был предназначен, поэтому я бы никогда не использовал это в производственной системе.
Если вам действительно нужно выполнить такой запрос, я рекомендую использовать инструмент агрегирования в памяти, например Spark.
Кроме того, поскольку первоначальный вопрос был о ORDER BY
, я недавно написал статью, которая лучше объясняет эту тему: https://www.datastax.com/dev/blog/we-shall-have-order