Оптимизация запроса, использующего арифметические операции в предложении WHERE - PullRequest
1 голос
/ 25 апреля 2019

Мне нужно получить записи, срок действия которых истекает сегодня.Срок годности рассчитывается динамически с использованием двух других полей (startDate и durationDays):

SELECT * FROM subscription WHERE startDate + durationDays < currentDate() 

Имеет ли смысл добавлять два индекса для этих двух столбцов?Или я должен рассмотреть добавление нового столбца expirationDate и создать индекс только для него?

Ответы [ 2 ]

1 голос
/ 26 апреля 2019
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 в конце, чтобы действовать в качестве разрыва связи для уникальности.
1 голос
/ 26 апреля 2019

Одним из основных различий между Cassandra и реляционными базами данных является то, что определение таблиц зависит от запроса, который будет использоваться.Условие того, как будут извлечены данные (WHERE statement), должно быть включено в первичный ключ, поскольку он будет работать лучше, чем индекс в таблице.

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

...