2015-12-22 2 views
8

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

CREATE TABLE journeydetails(
bucketid text, 
vehicleid text, 
starttime timestamp, 
stoptime timestamp, 
travelduration bigint, 
PRIMARY KEY (bucketid,vehicleid,starttime,travelduration) 
); 

Где:

  1. bucketid: - ключ раздела, который представляет собой сочетание месяц и год
  2. vehicleid: -Уникальная Идентификатор автомобиля
  3. STARTTIME : - время начала поездки
  4. окончание: - окончание поездки
  5. travelduration: - продолжительность путешествия в миллисекундах DS

Мы хотели бы выполнить следующий запрос - получить все странствия автомобиля - 1234567 между 2015-12-1 и 2015-12-3, поездки длительностью больше 30 минут

Когда я запускаю этот запрос:

select * from journeydetails where bucketid in('2015-12') and vehicleid in('1234567') 
    and starttime > '2015-12-1 00:00:00' and starttime < '2015-12-3 23:59:59' 
    and travelduration > 1800000; 

Я получаю этот результат:

InvalidRequest: code=2200 [Invalid query] message="Clustering column "travelduration" 
cannot be restricted (preceding column "starttime" is restricted by a non-EQ relation) 

У кого-нибудь есть рекомендация по устранению этой проблемы?

ответ

15
select * from journeydetails where bucketid in('2015-12') and vehicleid in('1234567') 
    and starttime > '2015-12-1 00:00:00' and starttime < '2015-12-3 23:59:59' 
    and travelduration > 1800000; 

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

Ваши строки разделены bucketid, а затем сортируется на диске vehicleid, starttime и travelduration. Поскольку вы уже выполняете запрос диапазона (отношение, отличное от EQ), на starttime, вы не можете ограничить указанный ниже ключ. Это связано с тем, что ограничение travelduration может дисквалифицировать некоторые из строк в вашем состоянии диапазона. Это приведет к неэффективному, непрерывному чтению. Cassandra разработан, чтобы защитить вас от написания запросов (таких как это), которые могут иметь непредсказуемую производительность.

Вот две альтернативы:

1- Если вы могли бы ограничить все из ваших ключевых столбцов до travelduration (с равенства отношения), то вы могли бы применить на ваш больше, чем условие:

select * from journeydetails where bucketid='2015-12' and vehicleid='1234567' 
    and starttime='2015-12-1 00:00:00' and travelduration > 1800000; 

Конечно, ограничение на точный starttime может быть не очень полезным.

2 Еще один подход заключается в том, чтобы полностью опустить travelduration, а затем ваш исходный запрос будет работать.

select * from journeydetails where bucketid='2015-12' and vehicleid='1234567' 
    and starttime > '2015-12-1 00:00:00' and starttime < '2015-12-3 23:59:59'; 

К сожалению, Cassandra не обеспечивает большую степень гибкости запросов.Многие люди нашли успех, используя решение, например, Spark (наряду с Cassandra) для достижения такого уровня отчетности.

И только боковое примечание, но не используйте IN, если вам не нужно. Запрос с IN похож на использование вторичного индекса, поскольку Cassandra должен поговорить с несколькими узлами, чтобы удовлетворить ваш запрос. Вызов его одним предметом, вероятно, не слишком большой. Но IN является одним из тех старых привычек RDBMS, которые вы должны действительно сломать, прежде чем слишком глубоко погрузиться в Cassandra.

+0

Спасибо за комментарии Арон ... Я исследую Искра как альтернативу – sam1977

 Смежные вопросы

  • Нет связанных вопросов^_^