Подходящий способ денормализации таблиц Кассандры для поддержки похожих запросов с дополнительными параметрами
Моя модель данных очень проста. Он моделирует посещения веб-страниц.
Вот как выглядит моя модель Visit (синтаксис - синтаксис Express-Cassandra):
fields: {
id: {
type: 'uuid',
rule: {
required: true,
message: 'id is required'
}
},
userId: {
type: 'int',
rule: {
required: true,
message: 'userId is required'
}
},
dateOfVisit: {
type: 'timestamp',
rule: {
required: true,
message: 'dateOfVisit is required'
}
},
urlPort: 'int',
urlHost: {
type: 'text',
rule: {
required: true,
message: 'urlHost is required'
}
},
urlPath: 'text',
urlQuery: 'text',
urlProtocol: {
type: 'text',
rule: {
required: true,
message: 'urlProtocol is required'
}
},
urlHash: 'text',
pageTitle: 'text'
},
key: [['id'], 'dateOfVisit'],
clustering_order: {'dateOfVisit': 'desc'}
У меня есть несколько вопросов об этой модели:
Вопрос 1:
Я уверен, что хочу сохранить части URL-адреса вместо того, чтобы хранить весь URL-адрес в виде одной строки, потому что это позволяет мне легче выполнять запросы на посещения определенного домена, посещения определенного пути в домене, посещения защитить страницы от посещений небезопасных страниц, ссылки с защищенных страниц на небезопасные (или обратные) и т. д.
Но было бы лучше хранить части URL как A) отдельные столбцы или B) как один столбец Map.
Кроме того, мне придется создавать дополнительные таблицы с различными первичными ключами только для поддержки всех различных запросов от запросов к различным частям URL-адреса?
Вопрос 2
У меня будет несколько разных способов запросить данные.
- Получить все посещения всех пользователей
- Получить все посещения для одного пользователя
- Получите все посещения в данный день или сгруппированы по часам в течение данного дня
- Получить все посещения данного домена
- Подсчитать все посещения данного домена, сгруппированные по пути
Итак, учитывая различные типы запросов, как мне хранить эту модель?
В настоящее время у меня в основном одни и те же поля, хранящиеся в нескольких таблицах только с разными первичными ключами (одна таблица с просто (id) для поддержки "получить все посещения всех пользователей", другая таблица с (id, userId) для поддержки "получить все посещения" для конкретного пользователя "и т. д.
Такое ощущение, что создается несколько копий данных только для поддержки по существу одного и того же запроса, но с одним дополнительным условием к предложению where.
Есть ли лучший способ смоделировать это?
1 ответ
На вопрос 1: поскольку компоненты URL-адреса всегда имеют одинаковые ключи (хост, порт, путь и т. Д.), Более эффективно иметь их как отдельные столбцы, а не как карту. Особенно в Cassandra 3 (или грядущей Scylla 3.0), где новый, более эффективный формат файла не требует повторения имен столбцов для каждой строки - но такие повторы будут необходимы для карты (которая, теоретически, может иметь разные ключи в каждом экземпляре).
На вопрос 2: одна вещь, которую вы могли бы сделать вместо того, чтобы поддерживать несколько таблиц самостоятельно (и всегда беспокоиться, если содержимое этих разных таблиц согласованно), вы могли бы использовать функцию Материализованных представлений (опять же, добавленную в Cassandra 3 и в Scylla 3), которая поддерживает все эти разные таблицы для вас. Это все еще потребует дополнительного места на диске для всех этих таблиц, но упростит ваше приложение. Другая вещь, которую вы можете сделать, - это использовать вторичные индексы, которые не дублируют все данные, а скорее создают дополнительные таблицы индексов, которые позволяют найти исходные данные в таблице. Например, такая вспомогательная таблица будет использоваться для получения, с учетом URL-пути, списка посещений (ключей к исходной таблице), имеющих этот путь. Но вам не нужно вести эту таблицу самостоятельно - все, что вам нужно сделать, это попросить проиндексировать определенный столбец, и Cassandra будет автоматически поддерживать эту таблицу для вас и использовать ее в запросах, которые ищут определенное значение этого столбца.