Я новичок в Cassandra и ищу лучший метод моделирования данных, которые имеют следующую общую структуру:
Данные основаны на «пользователях» (для каждого клиента), каждый из них предоставляет большой файл данных, содержащий около 500–2 млн записей (периодически обновляется несколько раз в день - иногда полное обновление, а иногда только дельты).
Каждый файл данных имеет определенные обязательные поля данных (~ 20 обязательных), но может добавлять дополнительные столбцы по своему усмотрению (до ~ 100).
дополнительные поля данных НЕ обязательно одинаковы для разных пользователей (названия полей или типы этих полей).
Пример (формат csv :)
user_id_1.csv
| column1 (unique key per user_id) | column2 | column3 | ... | column10 | additionalColumn1 | ...additionalColumn_n |
|-----------------------------------|-----------|----------|---------|------------|---------------------|------------------------|
| user_id_1_key_1 | value | value | value | value | ... | value |
| user_id_1_key_2 | .... | .... | .... | .... | ... | ... |
| .... | ... | ... | ... | ... | ... | ... |
| user_id_1_key_2Million | .... | .... | .... | .... | ... | ... |
user_id_XXX.csv (notice that the first 10 columns are identical to the other users but the additional columns are different - both the names and their types)
| column1 (unique key per user_id) | column2 | column3 | ... | column10 | additionalColumn1 (different types than user_id_1 and others) | ...additional_column_x |
|-----------------------------------------------------------|-----------|----------|---------|------------|-----------------------------------------------------------------|-------------------------|
| user_id_XXX_key_1 | value | value | value | value | ... | value |
| user_id_XXX_key_2 | .... | .... | .... | .... | ... | ... |
| .... | ... | ... | ... | ... | ... | ... |
| user_id_XXX_key_500_thousand (less rows than other user) | .... | .... | .... | .... | ... | ... |
Я рассмотрел несколько вариантов:
Вариант 1:
- Создайте «глобальное» пространство ключей
- Создайте большую таблицу "данных", содержащую все
Объедините столбец user_id со всеми другими столбцами большой таблицы (включая необязательные столбцы). Первичный ключ становится user_id + "column_1" (column_1 уникален для user_id)
Keyspace +--------------------------------------------------------------------------+ | | | | | Data_Table | | + +--------+-------+--------------------------+-----+ | | | | | | | | | | | +-------------------------------------------------+ | | | | | | | | | | many rows | +-------------------------------------------------+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Many columns | | | | | | | +------------------------> | | | | | | | | | | | | | +-------------------------------------------------+ | | v +-------------------------------------------------+ | | | +--------------------------------------------------------------------------+
Несколько вещей, которые я замечаю сразу:
- User_id повторяется столько раз, сколько записей для каждого пользователя.
- Строки очень редки для дополнительных столбцов (пустые нулевые значения), так как пользователи не обязательно разделяют их.
- Количество пользователей относительно невелико, поэтому количество дополнительных столбцов невелико (максимум 10К столбцов)
- Я мог бы сжать данные дополнительных столбцов для каждого пользователя в один столбец под названием «метаданные» и поделиться ими для всех пользователей.
Вариант 2:
Создать пространство ключей для каждого User_id
Создайте таблицу "данных" для каждого пространства ключей
+-----------------------------------------------------------------------------------+
| column_1 | column_2 | ... | column_n | additional_column_1 | additional_column_n |
+-----------------------------------------------------------------------------------+
keyspace_user1 keyspace_user2 keyspace_user_n
+----------------+ +---------------+ +---------------+
| | | | | |
| | | | | |
| +-+-+--+-+ | | +-+--+--+ | | +--+--+---+ |
| | | | | | | | | | | | | many keyspaces | | | | | |
| | | | | | | | | | | | | +-------------> | | | | | |
| | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | |
| +--------+ | | +-------+ | | +---------+ |
+----------------+ +---------------+ +---------------+
Примечания:
- Множество пространств ключей (пространство ключей на пользователя)
- Избегает добавления значения user_id для каждой строки (я могу использовать имя ключевого пространства в качестве идентификатора пользователя)
- Очень мало таблиц на пространство ключей (в этом примере только 1 таблица на пространство ключей)
Вариант 3:
1) Создайте глобальное пространство ключей 2) Создайте таблицу для user_id (обязательные столбцы, а также их дополнительные столбцы для их таблицы)
+---------------------------------------------------------------+
| Keyspace |
| |
| user_1 user_2 user_n |
| +--+---+--+ +--+--+--+ +--+--+--+ |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| +--+---+--+ +--+--+--+ +--+--+--+ |
| |
| |
+---------------------------------------------------------------+
Примечания
- Глобальное пространство ключей
- Таблица на user_id ("много" таблиц)
- Избегает дублирования идентификатора пользователя в строке
Вариант 4: (Есть ли в этом смысл?)
Создайте несколько пространств ключей (например, количество пространств ключей "x"), каждое из которых содержит диапазон таблиц (таблица для каждого пользователя)
keyspace_1 keyspace_x
+---------------------------------------------------------------+ +---------------------------------------------------------------+
| | | |
| | | |
| user_1 user_2 user_n/x | | user_n-x user_n-x+1 user_n |
| +--+---+--+ +--+--+--+ +--+--+--+ | | +--+------+ +--+--+--+ +--+--+--+ |
| | | | | | | | | | | | | | "X" keyspaces | | | | | | | | | | | | | |
| | | | | | | | | | | | | | +---------------------> | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | |
| +--+---+--+ +--+--+--+ +--+--+--+ | | +--+---+--+ +--+--+--+ +--+--+--+ |
| | | |
| | | |
+---------------------------------------------------------------+ +---------------------------------------------------------------+
Примечания:
- Несколько пространств клавиш
- Несколько таблиц на пользователя
- Требуется «поиск», чтобы выяснить, какое пространство ключей содержит требуемую таблицу.
Вариант 5:
Разделение данных на несколько таблиц и несколько пространств ключей
Примечания: 1. В некоторых случаях требуется "объединение" информации из нескольких таблиц 2. Кажется более сложным
Общие примечания для всех сценариев:
- Записи намного меньше, чем чтения
- Многие миллионы чтений в день
- Трафик колеблется в зависимости от user_id - у некоторых user_ids много трафика, а у некоторых user_ids гораздо меньше трафика. Потребуется настроить по этому показателю
- Некоторые user_ids обновляются (записываются) чаще, чем другие
- У нас есть несколько центров обработки данных в разных регионах, и мы должны синхронизировать
- У каждого первичного ключа есть длинный хвост (к некоторым ключам обращаются много раз, к другим - редко)