Комментарии 16
Получается, что C* нельзя в лоб использовать для хранения time-series данных, например значений данных с датчиков? (Я о проблеме Large Partition).
Другими словами структура данных вида:
CREATE TABLE sensor_data (
device_id uuid,
date_time timestamp,
data double,
PRIMARY KEY (device_id, date_time)
);
является очень и очень неэффективной.
Что можете посоветовать для данного случая, основываясь на вашем опыте?
является очень и очень неэффективной.
Так используйте композитный Partition Key:
PRIMARY KEY ((device_id, date_time))
В вашем же случае партиционирование идет только по device_id.
Если и этого недостаточно — можно добавить еще какой-нибудь искусственный ключ.
Но надо не забывать что в этом случае запросы должны будут включать и device_id и date_time. Либо делать запросы с полным сканированием.
Можно использовать не timestamp, а, например, номер дня года. Или номер дня с начала эпохи :) Тогда можно получить данные за нужный период запросом по первичному ключу.
SELECT * FROM sensor_data WHERE device_id=? and date_time > ? and date_time < ?
а это единственное, что мне нужно делать с этими данными
Спасибо!
Кстати, после какого размера партиции начинается проседание? с точностью до порядка, можете подсказать. 1K, 10K, 100K, 500K?
Думал, может есть всё-таки более элегантное решение…
На кластерных ключах его не может быть в принципе, т.к. он определяет на каком хосте в кластере лежат данные. А если они размазаны по более чем 1 хосту, то выборка уже не будет быстрой и это нарушает принципы Кассандры. Для range-выборок в идеале нужно юзать вторичные ключи, но у них свои проблемы. SASI-индексы решили многие из их проблем, но у них свои косяки (см ниже).
Кстати, после какого размера партиции начинается проседание? с точностью до порядка, можете подсказать. 1K, 10K, 100K, 500K?
It depends :) Посмотри вот эту презентацию: www.slideshare.net/DataStax/myths-of-big-partitions-robert-stupp-datastax-cassandra-summit-2016
Общий принцип — на каждые Х GB партиции нужно Y MB кеша в хипе.
Зависит от того какие запросы на чтение должны поддерживаться. Зачастую time-series данные имеет смысл разбивать по периодам, например, по дням, неделям и тому подобное, в зависимости от того как много данных добавляется в этот период и как для пользователя имеет смысл отображать эти данные. Этот подход иногда называют бакетированием (от bucket). Для вашего примера можно использовать составной partition key из device_id и, например, даты.
CREATE TABLE sensor_data (
device_id uuid,
data_date date
date_time timestamp,
data double,
PRIMARY KEY ((device_id, date), date_time)
);
Все значения с одного устройства за одну дату будут попадать в одну партицию, но для разных дат и одного устройства будут разные партиции.
При этом понадобится вторая таблица для хранения самих дат, чтобы была возможность по device_id найти даты.
CREATE TABLE sensor_dates (
device_id uuid,
data_date date
PRIMARY KEY (device_id, date)
);
При добавлении значение делаем два Insert в обе таблицы.
При чтении есть варианты:
- Когда диапазон не задан и нужно получить все данные, то запрашиваем все даты по device_id из sensor_dates, затем по каждой дате запрашиваем сами значение из sensor_data. Это может быть долго, если дат много, так как придется сделать много запросов.
- Когда указан диапазон, то даты можно получить из указанного диапазона и опять же запросить данные по датам из sensor_data.
Этот подход не всегда работает, например если данных для одного устройства очень много и есть требование в реальном времени получать все эти данные, например для подсчета статистики. Но тут уж как ни крути будет медленно.
Но чаще встречается кейс, когда нужны данные именно за какой-то не очень большой период, здесь нужно грамотно выбрать период по которому данные будут разделятся, с одной стороны нужно выбрать максимально большой период, чтобы уменьшить количество запросов при чтении данных, с другой стороны этот период должен обеспечивать адекватный размер партиции.
A на ScyllaDB смотрели?
ScyllaDB — новая производительная NoSQL, совместимая с Apache Cassandra, от создателей Linux KVM
Если я правильно понимаю — я могу её использовать без изменений вместо C*? Просто вот так взять поменять адреса подключения и всё?
И там не будет проблем с Large Partiton? Или все перечисленные в статье недостатки останутся, только пошустрее будет? (если верить разработчикам )))
Почти полтора года прошло…
Но во многом — крайне удобная БД и да, практически без альтернатив. Разве что Aerospike подошел бы, но только в энтерпрайз версии — в опенсурсную даже Tombstone не завезли…
Она все данные при старте в память грузит (по крайней мере так было 4 года назад) — не для этого решения.
Нет. Она вполне умеет персистить на диск. Но из-за отсутствия Tombstone в opensource-версии все удаленные данные приезжают обратно после перезапуска ноды. Единственный выход этого избежать — удалять всё с ноды и давать ей отреплицироваться после запуска. Но это по понятным причинам занимает много времени. Если твой юзкейс только добавление — то вполне может прокатить.
И еще Apache Kudu сейчас дошла до продакшена — сравнима с кликхаусом. Индексов там также пока нет (хотя планируются), но скорость выборки и без них огромная.
Cassandra для хранения метаданных: успехи и провалы