SELECT * FROM subscription WHERE startDate + durationDays < currentDate()
Мне интересно, как Кассандра обрабатывает такой фильтр, как в моем примере?Делает ли он полное сканирование?
Прежде всего, ваш вопрос основан на способности CQL выполнять арифметику (дата).Он не может.
> SELECT * FROM subscription WHERE startDate + durationDays < currentDate();
SyntaxException: line 1:43 no viable alternative at input '+' (SELECT * FROM subscription WHERE [startDate] +...)
Во-вторых, функция currentDate()
не существует в Cassandra 3.11.4.
> SELECT currentDate() FROM system.local;
InvalidRequest: Error from server: code=2200 [Invalid query] message="Unknown function 'currentdate'"
Что работает в Cassandra 4.0, котораяпоскольку он еще не выпущен, вам действительно не следует его использовать.
Итак, давайте предположим, что вы создали свои вторичные индексы для startDate
и durationDays
и просто запрашиваете их,без какой-либо арифметики.
Выполняет ли он полное сканирование таблицы?
АБСОЛЮТНО.
Причина заключается в том, что запрос только по столбцам вторичного индекса делаетнет ключа раздела.Поэтому он должен искать эти значения во всех разделах на всех узлах.В большом кластере ваш запрос, скорее всего, истечет время ожидания.
Кроме того, когда он находит совпадающие данные, он должен продолжать запрашивать.Поскольку эти значения не являются уникальными;вполне возможно, что есть несколько результатов, которые будут возвращены.Карлос на 100% правильно советует вам перестроить таблицу на основе того, что вы хотите запросить.
Рекомендации:
- Старайтесь не строить таблицу со вторичными индексами.Как всегда.
- Если вам нужно построить таблицу со вторичными индексами, попробуйте включить ключ разделения в ваше предложение
WHERE
, чтобы сохранить запрос изолированным для одного узла. - Любая фильтрациядля динамических (вычисляемых) значений необходимо выполнить на стороне приложения.
- В вашем случае, возможно, имеет смысл создать столбец с именем
expirationDate
, выполнить арифметику даты в своем приложении и затем INSERT
это значение в вашу таблицу. - Вы также захотите следовать шаблону «временного сегмента» для обработки данных временного ряда (как это и выглядит).Скажите, что
month
работает как «ведро» (это может или не может быть для вашего случая использования).PRIMARY KEY ((month),expirationDate,id)
было бы хорошим ключом.Таким образом, все подписки на определенный месяц хранятся вместе, сгруппированные по expirationDate
, с id
в конце, чтобы действовать в качестве разрыва связи для уникальности.