Как смоделировать повторяющуюся информацию о многих записях на cassandra

У меня есть огромная таблица с сотнями миллиардов записей, и я хочу добавить в эту таблицу поле, одно и то же значение которого будет повторяться для миллионов записей. Я не знаю, как эффективно смоделировать это в кассандре. Позвольте мне уточнить:

У меня есть общая таблица:

CREATE TABLE readings (
    key int,
    key2 int,
    time timestamp,
    name text,
    PRIMARY KEY ((key, key2) time)
)

Эта таблица содержит более 700 000 000 записей. Я хочу создать в этой таблице поле с именем source. В этом поле указано, откуда была получена запись (поскольку программа имеет множество способов получения информации о таблице reading). Одно возможное значение для этого поля — "XML: path\to\file.xml" или "Direct import from the X database" или даже "Manually added". Я хочу, чтобы это было описательное поле, используемое исключительно для последующего обслуживания в базе данных, где мы хотим манипулировать только записями из данного источника.

Запросы, которые я хочу запустить, которые я не могу сейчас выполнить:

  • Какие записи в таблице readings были получены из данного источника?
  • Каков источник данной записи?

Решением для меня было бы создать таблицу, например:

CREATE TABLE readings_per_source(
    source text,
    key int,
    key2 int,
    time timestamp,
    PRIMARY KEY (source, key, key2, time)
)

что позволило бы мне выполнить первый запрос, но также означало бы, что я создал бы 700 000 000+ новых записей в моей базе данных с большим количеством информации, что заняло бы много ненужного места для хранения, поскольку десятки миллионов этих записей были бы имеют такое же значение для source.

Если бы это была реляционная среда, я бы создал поле source_id в таблице readings и таблицу source с полями id (PK) и name, что означало бы сохранение только дополнительного целого числа для каждой строки в таблице readings и новую таблицу с таким же количеством записей. так как разные источники были.

Как можно смоделировать это в cassandra?


person Lucas Franceschi    schedule 31.05.2016    source источник


Ответы (2)


Ваша схема

CREATE TABLE readings_per_source(
    source text,
    key int,
    key2 int,
    time timestamp,
    PRIMARY KEY (source, key, key2, time)
)

— очень плохая идея, потому что source — это ключ раздела, и у вас могут быть миллионы записей, использующих один и тот же источник, например. очень-очень широкий раздел --> горячие точки

Для вашего второго запроса What is the source of a given record? это довольно тривиально, если вы получаете доступ к данным, используя первичные ключи записи (key, key2). Столбец source можно добавить в таблицу как обычный столбец.

Для первого запроса Which records on the readings table were gotten from a given source? это сложнее. Идея здесь состоит в том, чтобы получить все записи, имеющие один и тот же источник.

Вы понимаете, что этот запрос потенциально может вернуть десятки миллионов записей?

Если это то, что вы хотите сделать, есть решение, используйте новый вторичный индекс SASI (прочитайте мой сообщение в блоге для получения подробной информации) и создайте индекс для столбца source

CREATE TABLE readings (
    key int,
    key2 int,
    time timestamp,
    name text,
    source text,
    PRIMARY KEY ((key, key2), time)
)

CREATE CUSTOM INDEX source_idx ON readings(source) 
USING 'org.apache.cassandra.index.sasi.SASIIndex'
WITH OPTIONS = {
     'mode': 'PREFIX', 
     'analyzer_class': 'org.apache.cassandra.index.sasi.analyzer.NonTokenizingAnalyzer',
     'case_sensitive': 'false'
};

Затем, чтобы получить все записи с одним и тем же источником, используйте на стороне сервера. пейджинг функция драйвера Java (или любого другого драйвера Datastax)

person doanduyhai    schedule 01.06.2016
comment
Да, я знаю, что запрос может вернуть много записей, и это своего рода цель. Может ли это быть проблемой? Я имею в виду возврат миллионов записей с помощью одного запроса. Кроме того, я думал о создании какого-то индекса, но не знал, как это сделать, ваш ответ очень помогает. Однако остается один вопрос: простое добавление столбца и повторение значения денормализованным способом не приведет ли это к чрезмерному использованию памяти? - person Lucas Franceschi; 02.06.2016
comment
Кроме того, я использую драйвер python и заметил, что драйвер уже отображает результаты больших запросов. Нужно ли настраивать что-либо иначе, чем то, что он уже делает? - person Lucas Franceschi; 02.06.2016
comment
Однако остается один вопрос: простое добавление столбца и повторение значения денормализованным способом не приведет ли это к чрезмерному использованию памяти? --› Теоретически да, но на практике, если у вас включено сжатие диска (по умолчанию), это должно помочь сэкономить место. - person doanduyhai; 02.06.2016
comment
Я заметил, что драйвер уже выводит результаты больших запросов. Нужно ли настраивать что-либо иначе, чем то, что он уже делает? --› Вы можете настроить fetchSize для подкачки, чтобы обеспечить наилучшую производительность. Слишком маленький размер страницы снижает производительность, поскольку клиенту необходимо отправлять много запросов. Слишком большой размер страницы может убить координатора. Хорошая ценность страницы — это что-то между 1000 и 100 000 макс. - person doanduyhai; 02.06.2016
comment
Да, если я не ошибаюсь, размер выборки по умолчанию составляет 5000, я полагаю, что это здоровое значение, принимая во внимание то, что вы только что сказали. Я полагал, что сжатие может сэкономить место, поскольку содержимое часто повторяется. Большое спасибо за вдумчивые ответы, я еще не проверял, но я убежден, что это решает проблему. Ваше здоровье! - person Lucas Franceschi; 02.06.2016

http://www.datastax.com/2015/03/how-to-do-joins-in-apache-cassandra-and-datastax-enterprise — довольно хорошая статья о том, как объединять таблицы в Cassandra.

нормализованные данные всегда будут занимать меньше памяти, чем денормализованные (плоские) данные (при условии, что связанные данные больше, чем ключ, используемый для объединения таблиц вместе), но требуют соединений, которые требуют больше вычислительных ресурсов во время запросов.

Всегда есть компромисс. Существует также компромисс, касающийся состояния с полностью нормализованными данными, например, клиент, который меняет адрес. В полностью нормализованной схеме после изменения адреса все счета-фактуры для клиента, прошлые и настоящие, показывают новый адрес. Это не всегда желательно.

Часто желательно частично нормализовать, чтобы обеспечить историческое состояние записей, где важно показать состояние данных в данный момент времени, например, в счетах. В этом случае вы должны сохранить копию данных адреса клиента в счете-фактуре во время создания счета-фактуры.

Это особенно важно для ценообразования и налогов. Вы хотите, чтобы цена/налог хранились в счете-фактуре, чтобы вы могли показать, что клиент заплатил во время создания счета-фактуры, поэтому, когда учет ведется ежемесячно, ежегодно и далее, цены в данном счете-фактуре верны на дату в счет-фактуру, даже если цены на товары изменились. В противном случае у вас будет бухгалтерский кошмар!

При принятии решения о нормализации/денормализации схемы необходимо учитывать гораздо больше, чем просто место для хранения.

Извините за сумбурность...

person Neil Davis    schedule 31.05.2016
comment
Я не думаю, что на самом деле я хочу найти способ соединения таблиц, а смоделировать проблему, не обращаясь к другим ресурсам, таким как spark или соединители ODBC. Мой вопрос имеет немного теоретический тон, так что ваша бессвязность прощена. Очень информативный ваш ответ, я приму его во внимание. Спасибо! - person Lucas Franceschi; 31.05.2016