Оптимизация ежедневного хранения данных в реляционной БД - PullRequest
2 голосов
/ 22 июля 2010

Обновление: был комментарий, что вопрос не ясен, что я сделал прыжок логики, утверждая, что у меня будет 118 миллиардов строк. Я отредактировал текст ниже, чтобы уточнить вещи. Смотрите выделенный курсивом текст ниже

Я боролся с этим некоторое время, даже пошел несколькими путями, но теперь я обращаюсь к сообществу за идеями. Во-первых, проблема - хранить шесть ежедневных переменных в течение ~ 25 лет для ячеек в сетке.

  • Количество переменных = 6
  • Количество ячеек ~ 13 миллионов
  • Количество дней ~ 9125 (25 * 365)

Оптимизировать магазин для двух разных типов запросов -

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

Запрос второй: получение значений для всех дней или продолжительности дней для одной переменной для одной ячейки. Это похоже на извлечение столбца из таблицы, в которой каждая строка содержит все переменные за один день.

Итак, я приступил к проектированию БД. Единственная таблица , где каждая строка - это значения за один день для одной ячейки , должна выглядеть так:

CREATE TABLE d (
    yr      SMALLINT,
    yday    SMALLINT,
    a       SMALLINT,
    b       SMALLINT,
    d       SMALLINT,
    e       SMALLINT,
    f       SMALLINT,
    g       SMALLINT,
    cell_id INTEGER
)
WITH (
    OIDS=FALSE
)

Данные будут выглядеть так

yr      yday    a   b   c   d   e   f   g   cell_id
----------------------------------------------------
1980    1       x   x   x   x   x   x   x   1
1980    2       x   x   x   x   x   x   x   1
1980    3       x   x   x   x   x   x   x   1
..
1980    365     x   x   x   x   x   x   x   1
...
1981    1       x   x   x   x   x   x   x   1
1981    2       x   x   x   x   x   x   x   1
1981    3       x   x   x   x   x   x   x   1
..
1981    365     x   x   x   x   x   x   x   1

Проблема: в приведенной выше таблице будет 13 м * 9125 строк ~ 118 млрд. Строк. Огромные индексы, медленные запросы, серьезные проблемы с загрузкой данных и т. Д.

Итак, я разбил таблицу на годы, вот так

CREATE TABLE d_<yyyy> (
    CHECK ( yr = <yyyy> )
) INHERITS (d)

Хммм ... до сих пор нет удовлетворения. В итоге у меня было 1 + 25 таблиц, но в каждой из таблиц года было ~ 4,75 миллиарда строк, а запросы все еще были очень медленными.

Итак, я разделил все по годам и дням, вот так

CREATE TABLE d_<yyyy>_<yday> (
    CHECK ( yr = <yyyy> AND yday = <yday> )
) INHERITS (d)

Каждая таблица теперь имеет 13 миллионов строк и работает достаточно быстро (хотя все еще не достаточно быстро), но теперь у меня есть таблицы 9K. Это имеет свои проблемы. Я больше не могу запрашивать основную таблицу, так как Pg пытается заблокировать все таблицы и не хватает памяти. Кроме того, я больше не могу выполнять запрос два выше. Я мог бы сделать что-то вроде

SELECT a FROM d_1980_1 WHERE cell_id = 1 
UNION 
SELECT a FROM d_1980_2 WHERE cell_id = 1 
UNION 
SELECT a FROM d_1980_3 WHERE cell_id = 1 
UNION 
SELECT a FROM d_1980_4 WHERE cell_id = 1 
UNION 
...

Но вышесказанное вряд ли оптимально.

Любые предложения, идеи, мозговые штурмы будут оценены. Возможно, Pg, или даже RDBMS, не является подходящим инструментом для решения этой проблемы, и в этом случае приветствуются также предложения по альтернативам.

1 Ответ

1 голос
/ 25 июля 2010

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

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

Предполагая, что доступ по дате является наиболее важным, вы можете расположить таблицу следующим образом:

CREATE TABLE d (
    day      DATE,
    a       SMALLINT[],
    b       SMALLINT[],
    ...
);

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

Запрос 1,

Извлечение значения одного var для всех или части ячеек за один день.

выполняется, например,

SELECT a FROM d WHERE day = '1981-01-01'

Запрос 2,

Извлечение значений для всех дней или продолжительности дней дляодна переменная для отдельной ячейки.

будет иметь вид

SELECT a[1000] FROM d WHERE day BETWEEN '1981' AND '1982'

Я считаю, что к большим массивам в PostgreSQL обращаются без фактической загрузки всей структуры данных.Я знаю, что BLOB.Если это так, это решение может быть достаточно быстрым для вас.В противном случае я бы предложил сделать еще один просмотр данных, который оптимизирует доступ по ячейкам.

...