Моделирование временных рядов (с датой начала и окончания) в Кассандре
Я делаю моделирование данных временных рядов, где у меня есть дата начала и дата окончания событий. Мне нужно запросить эту модель данных, как показано ниже:
Select * from tablename where startdate>'2012-08-09' and enddate<'2012-09-09'
Я ссылался на следующую ссылку в предложении cql where, но не смог этого добиться. Есть ли способ сделать это? Я также могу изменить модель данных или любые настройки cql. Я использую Cassandra 2.1.
1 ответ
Мне пришлось решить аналогичную проблему на одной из моих прежних должностей. Это один из способов, которым вы могли бы достичь этого...
Мне нужно сделать запрос к этой модели данных, как показано ниже:
Select * from tablename where startdate>'2012-08-09' and enddate<'2012-09-09'
,
Есть две проблемы моделирования, мешающие этому запросу работать. Прежде всего, чтобы выполнить запрос диапазона, сначала нужно ограничить запрос ключом раздела. На основе данных временных рядов лучше всего создать нечто, называемое временным интервалом. В этом примере я разделю данные по месяцам, используя ключ monthbucket
,
Другая проблема заключается в том, что вы можете выполнить запрос диапазона только для одного значения столбца / ключа. Это становится проблематичным, если вы хотите сделать запрос по дате начала и окончания. Одним из решений является сохранение каждой строки в таблице дважды и создание дополнительного ключа кластеризации для хранения значения того, является ли строка начальной или конечной строкой. Я просто позвоню в эту колонку beginend
,
Учитывая эти заметки, я создам таблицу, которая выглядит следующим образом:
CREATE TABLE events (
monthBucket TEXT,
eventDate TIMESTAMP,
beginEnd TEXT,
eventid UUID,
eventName TEXT,
PRIMARY KEY (monthBucket, eventDate, beginEnd, eventid))
WITH CLUSTERING ORDER BY (eventDate DESC, beginEnd ASC, eventid ASC);
- В большинстве реализаций временных рядов вы стремитесь больше заботиться о самых последних данных. С этой целью я сосредоточен на
eventDate
в порядке убывания. - Кроме того, поскольку у вас может быть несколько событий, начинающихся одновременно, вы также должны добавить дополнительный ключ кластеризации для обеспечения уникальности (
eventid
в этом случае).
После ВСТАВКИ некоторых строк, давайте просто запросим по ключу раздела от сентября 2015 года:
aploetz@cqlsh:stackru> SELECT * FROM events WHERE monthbucket='201509';
monthbucket | eventdate | beginend | eventid | eventname
-------------+--------------------------+----------+--------------------------------------+------------------------
201509 | 2015-09-25 23:59:59+0000 | E | a223ad16-2afd-4213-bee3-08a2c4dd63e6 | Hobbit Day
201509 | 2015-09-25 00:00:00+0000 | B | a223ad16-2afd-4213-bee3-08a2c4dd63e6 | Hobbit Day
201509 | 2015-09-24 23:59:59+0000 | E | 9cd6a265-6c60-4537-9ea9-b57e7c152db9 | Cassandra Summit
201509 | 2015-09-22 00:00:00+0000 | B | 9cd6a265-6c60-4537-9ea9-b57e7c152db9 | Cassandra Summit
201509 | 2015-09-19 23:59:59+0000 | E | b9fe9668-cef2-464e-beb4-d4f985ef9c47 | Talk Like a Pirate Day
201509 | 2015-09-19 00:00:00+0000 | B | b9fe9668-cef2-464e-beb4-d4f985ef9c47 | Talk Like a Pirate Day
(6 rows)
Как и в вашем примере, предположим, что я хочу запрашивать события между 18 и 24 сентября:
aploetz@cqlsh:stackru> SELECT * FROM events WHERE monthbucket='201509' AND eventdate > '2015-09-18' AND eventdate < '2015-09-24';
monthbucket | eventdate | beginend | eventid | eventname
-------------+--------------------------+----------+--------------------------------------+------------------------
201509 | 2015-09-22 00:00:00+0000 | B | 9cd6a265-6c60-4537-9ea9-b57e7c152db9 | Cassandra Summit
201509 | 2015-09-19 23:59:59+0000 | E | b9fe9668-cef2-464e-beb4-d4f985ef9c47 | Talk Like a Pirate Day
201509 | 2015-09-19 00:00:00+0000 | B | b9fe9668-cef2-464e-beb4-d4f985ef9c47 | Talk Like a Pirate Day
(3 rows)
Как видите, я должен получить три строки: начальную и конечную строки для "Talk Like A Pirate Day" и начальную строку для Саммита Кассандры 2015 года.
Как и в случае всех подходов к моделированию данных, необходимо сделать компромисс. В этом случае для моделирования запросов на обе даты компромисс заключается в том, что вам нужно дублировать строки. И, конечно же, для того, чтобы вообще иметь возможность разбрасывать запросы, вы должны выбрать хороший ключ раздела (monthbucket
), который предлагает соответствующие данные и необходимую гибкость запроса. В любом случае, попробуйте и посмотрите, сможете ли вы заставить его работать в вашем случае использования.
Изменить, чтобы ответить на вопросы:
Если я хочу найти все события с 25 ноября 2015 года по 25 ноября 2016 года. Как это могло быть возможно?
Вот где вам нужно определить оптимальное время для вашего приложения. Подумайте о своих наиболее распространенных запросах и смоделируйте их. Теперь вы не хотите хранить слишком много в одной строке (ведре), потому что это убьет ваше распределение данных. Поэтому постарайтесь найти удачный путь между гибкостью запросов и распределением данных.
В этом конкретном случае с monthBucket
вам нужно будет выполнить запрос для каждого отдельного месяца. Приложение, для которого я разработал это решение, никогда не смотрело на события целых лет. Если это шаблон запроса, который вам нужно поддерживать, то вам нужно немного увеличить время.
Есть ли способ удалить эту дублирующую строку только из набора результатов?
Нету. Дубликаты должны обрабатываться / игнорироваться на уровне приложения. Cassandra CQL имеет ключевое слово DISTINCT, но оно работает только с ключами раздела.
Можно ли сделать этот тип слияния на уровне Кассандры?
Нет, у Кассандры нет возможности объединяться в таблицы. И соединения на стороне приложения возможны, но неэффективны и технически являются антишаблоном.
Обработка данных на стороне приложения (будь то объединение или фильтрация), как правило, не очень хорошая идея. Но ключ к модерации. Если вы запрашиваете 20 событий и должны игнорировать дупсеты для некоторых из них, это не так уж сложно. Но запрос 20000000 событий и применение процесса на стороне приложения на этом томе не будет хорошо масштабироваться вообще. Опять же, здесь вы должны посмотреть на доступные варианты и решить, что будет работать для вашего приложения.