2017-02-12 7 views
1

Я разрабатываю базу данных для приложения аналитики. Мои данные загружаются из файла CSV. Этот файл содержит ряд двойных значений (может быть, более 100 тыс. Значений) для объекта с именем «feed».JSON столбец для массива double

Я хочу хранить эти массивы double в столбце JSON в PostgreSQL и «разделять» данные. Я выберу номер фактора (например: 1000), это означает, что для каждого JSON он содержит максимум 1000 значений. В результате, если у вас есть 3000 значений в CSV, то вы будете иметь 3 строки, каждая строка будет содержать JSON 1000 значений, как показано ниже:

Table feed 
---------------------------------------- 
| id | data | 
| 1 | { data: [1,2,3,4...1000]} 
| 2 | { data: [1001,1002,...,2000]} 
| 3 | { data: [2001,2002,...,3000]} 

Если вы хотите обновить любое значение, то я буду дублировать массив внутри каждого JSON с новым значением, а остальные будут равны -1.

Например, если вы хотите изменить значение 2002 (с индексом 1) до 4500, то таблица будет:

Table feed 
---------------------------------------- 
| id | data | 
| 1 | { data: [1,2,3,4...1000]} 
| 2 | { data: [1001,1002,...,2000]} 
| 3 | { data: [2001,2002,...,3000], new_data: [-1,4500,-1,-1...]} 

А может быть, я буду добавлять дополнительные столбцы метаданных для описания данных в формате JSON, такие as array_length, is_modifed .... для удобства обработки.

Я не знаю, с этим дизайном я могу легко выполнять операции CRUD? И это хорошо для рендеринга и обновления графика в реальном времени? Поскольку чтение, запись, обновление ... эти данные массива так часто. Может ли кто-нибудь дать мне несколько советов по этому поводу?

Благодаря

+0

Интересно, как вы могли придумать такую ​​надуманную схему. В чем смысл? Существуют ли какие-либо причины/требования, о которых мы не знаем, что привело вас к этому? – jcaron

+0

В большинстве случаев массив используется для рендеринга диаграммы, и когда кто-то редактирует какую-либо точку на диаграмме, это значение будет обновляться, а еще одна вещь - это опрос клиента для изменения новых данных для обновления графика. Поэтому я думаю, что использование JSON для удобного чтения и рендеринга – Barcelona

ответ

3

Использование данных JSON в сценарии, что вы описываете это очень плохая идея.

JSON is a lightweight data-interchange format и как таковой не особенно эффективен в качестве хранилища данных и манипулирования данных формата и PostgreSQL в качестве модели хранения реляционных данных не особенно подходят либо для манипулирования JSON (JSON имеет иерархическую структуру данных) или больших массивов.

Несколько более конкретные причины, почему ваша идея не является эффективным:

  • Ввод 1000 двойных значений в массиве дает структуру данных более чем 8000 байт (предполагается, что тип jsonb данных: 8000 байт для двойников, некоторые накладные расходы для самой структуры и ее дескрипторов, обычный json, скорее всего, даже будет больше, потому что каждое значение будет содержать не менее 8 символов, чтобы точно описывать величину каждого значения). Это означает, что таблица будет TOAST ed, что приводит к штрафу за производительность.
  • Для обновления одного значения в массиве требуется переписать всю запись (в основной таблице и в таблице TOAST), что крайне неэффективно.

Вам гораздо лучше использовать простую реляционную структуру внутри PostgreSQL с триггерами для реализации вашей логики. Если ваш графический клиент ожидает ввода документа JSON, PostgreSQL может сгенерировать его на лету.Например:

CREATE TABLE feed (
    "index" integer, 
    value  double precision 
); 

CREATE FUNCTION trf_upd_feed RETURNS trigger AS $$ 
BEGIN 
    -- This DELETE statement throws out unwanted data (the -1 values in your example) 
    -- Usually there will be very few rows (just 1?) that get deleted 
    DELETE FROM feed 
    WHERE ("index" - 1)/1000 = (NEW."index" - 1)/1000; -- integer division! 
    RETURN NEW; 
END; 
$$ LANGUAGE plpgsql; 

CREATE TRIGGER tr_feed_update 
BEFORE UPDATE ON feed 
FOR EACH ROW EXECUTE PROCEDURE trf_upd_feed(); 

Когда вам нужны данные для построения графиков вы можете запустить простой запрос, чтобы получить данные для среза значений как JSON объект:

SELECT json_build_object('data', arr) AS json_data 
FROM (
    SELECT json_agg(coalesce(feed.value, -1)) AS arr 
    FROM generate_series(1001, 2000) i(x) 
    LEFT JOIN feed ON feed."index" = i.x) sub; 

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

Alternative

Из вашего описания я получаю идею, что ваш клиент картирования поддерживает свой собственный кэш значений, а затем периодически опрашивает новые данные в базе данных. Если это так, вы должны изменить свою логику. Вместо того, чтобы изменять значения (удаление записей) при обновлении, вы должны сделать это, когда приложение для графического отображения считывает данные; для этого вам нужна функция вместо триггера обновления (так удалить, что один, если вы создали его уже):

CREATE FUNCTION chart_data (start_idx integer, end_idx integer) RETURNS json AS $$ 
DECLARE 
    json_data json; 
BEGIN 
    SELECT json_build_object('data', arr) INTO json_data 
    FROM (
     SELECT json_agg(coalesce(feed.value, -1)) AS arr 
     FROM generate_series(start_idx, end_idx) i(x) 
     LEFT JOIN feed ON feed."index" = i.x) sub; 

    -- Data has been read, so now it can be deleted 
    DELETE FROM feed 
    WHERE "index" BETWEEN start_idx AND end_idx; 

    RETURN json_data; 
END; 
$ LANGUAGE plpgsql VOLATILE STRICT; 

А потом просто называют `ВЫБЕРИТЕ chart_data (1001, 2000);

+0

Спасибо за ваш ответ, на самом деле у нас нет DBA, и я мало что знаю о PostgreSQL и насколько PG поддерживает JSON. Идея - всего лишь одно из предложений моей команды. Когда я должен использовать JSON для хранения? – Barcelona

+0

PG имеет функции манипулирования документами JSON (особенно полезными для двоичного типа данных jsonb), но в целом вы должны позволить PG хранить JSON и выполнять манипуляции на стороне клиента. PG может искать (и индексировать) простые JSON-документы (т.е. хорошо структурированные, но не слишком иерархически глубокие), но в целом вы хотите разобрать сложные структуры в модель отношения (одну или несколько таблиц) и глотать и генерировать JSON-документы, как показано в ответе , – Patrick