Я тестирую Cassandra как базу данных временных рядов.
Я создаю модель данных, как показано ниже:
CREATE KEYSPACE sm WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': 1 }; USE sm; CREATE TABLE newdata (timestamp timestamp, deviceid int, tagid int, decvalue decimal, alphavalue text, PRIMARY KEY (deviceid,tagid,timestamp));
В главном ключе я устанавливаю deviceid в качестве ключа раздела, который означает, что все данные с одинаковым идентификатором устройства будут записываться в один узел (означает ли это один компьютер или один раздел. Каждый раздел может иметь максимум 2 миллиарда строк), также если я запрашиваю данные в пределах тот же узел, поиск будет быстрым, я прав? Я новичок в Cassandra и немного растерялся в отношении ключа раздела и ключа кластеризации.
Большая часть моего запроса будет выглядеть следующим образом:
У меня будет около 2000 устройств, каждый deviceid будет иметь 60 пар tagid / value. Я не уверен, что это будут широкие ряды deviceid, timestamp, tagid / value, tagid / value ….
Я новичок в Cassandra и немного растерялся в отношении ключа раздела и ключа кластеризации.
Похоже, вы понимаете ключи разделов, поэтому я просто добавлю, что ваш ключ раздела помогает Cassandra выяснить, где (этот диапазон токенов) в кластере для хранения ваших данных. Каждый узел отвечает за несколько первичных диапазонов маркеров (при условии vnodes). Когда ваши данные записываются в раздел данных, они сортируются по вашим ключам кластеризации. Это также то, как он хранится на диске, поэтому помните, что ваши ключи кластеризации определяют порядок хранения ваших данных на диске.
Каждый раздел может иметь не более 2 миллиардов строк
Это не совсем так. Каждый раздел может поддерживать до 2 миллиардов ячеек . Ячейка – это, по существу, пара столбцов / значений. И ваши ключи кластеризации складываются в одну ячейку самостоятельно. Итак, вычислите свои ячейки, подсчитав значения столбцов, которые вы храните для каждой строки CQL, и добавьте еще одну, если используете столбцы кластеризации.
В зависимости от вашей строчной структуры строк, вероятно, будет ограничено гораздо меньше, чем 2 миллиарда строк. Кроме того, это просто ограничение хранения. Даже если вам удалось сохранить 1 миллион строк CQL в одном разделе, запрос на этот раздел будет возвращать так много данных, что это было бы неуклюже и, вероятно, тайм-аут.
если я запрашиваю данные в одном узле, поиск будет быстрым, я прав?
Это будет, по крайней мере, быстрее, чем многозадачные запросы, которые попадают в несколько узлов. Но независимо от того, будет ли он «быстрым», зависит от других вещей, например от того, насколько широки ваши ряды, и как часто вы делаете такие вещи, как удаление и обновление на месте.
Большая часть моего запроса будет выглядеть следующим образом:
select lastest timestamp of know deviceid and tagid Select decvalue of known deviceid and tagid and timestamp Select alphavalue of known deviceid and tagid and timestamp select * of know deviceid and tagid with time range select * of known deviceid with time range
Ваша текущая модель данных может поддерживать все эти запросы, за исключением последней. Чтобы выполнить запрос диапазона по timestamp
, вам нужно будет дублировать данные в новую таблицу и создать PRIMARY KEY для поддержки этого шаблона запроса. Это называется «основанным на запросах». Я бы построил таблицу запросов следующим образом:
CREATE TABLE newdata_by_deviceid_and_time ( timestamp timestamp, deviceid int, tagid int, decvalue decimal, alphavalue text, PRIMARY KEY (deviceid,timestamp));
Эта таблица может поддерживать запрос диапазона по timestamp
, а при разбиении на deviceid
.
Но самая большая проблема, которую я вижу с любой из этих моделей, – это «неограниченный рост строк». В принципе, по мере того, как вы собираете все больше и больше значений для своих устройств, вы будете приближаться к 2-миллиардному лимиту на каждый раздел (и, опять же, до этого все будет медленнее). То, что вам нужно сделать, – это использовать метод моделирования, называемый «балансировкой времени».
Например, я скажу, что я определил, что котировка по месяцам будет поддерживать меня под лимитом в 2 миллиарда ячеек и позволит использовать гибкость диапазона дат, в которой я нуждался. Если это так, я бы добавил дополнительный ключ monthbucket
и моя (новая) таблица выглядела бы так:
CREATE TABLE newdata_by_deviceid_and_time ( timestamp timestamp, deviceid int, tagid int, decvalue decimal, alphavalue text, monthbucket text, PRIMARY KEY ((deviceid,monthbucket),timestamp));
Теперь, когда я хотел запросить данные в определенном устройстве и в диапазоне дат, я бы также уточнил monthbucket
:
SELECT * FROM newdata_by_deviceid_and_time WHERE deviceid='AA23' AND monthbucket='201603' AND timestamp >= '2016-03-01 00:00:00-0500' AND timestamp < '2016-03-16 00:00:00-0500';
Помните, что monthbucket
– всего лишь пример. Для вас может быть deviceid
использовать четверть или даже год (при условии, что вы не храните слишком много значений на deviceid
в год).