Можно ли разделить значение и параметр в базе данных? - PullRequest
0 голосов
/ 23 мая 2018

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

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

параметр в [temperature,precipitation .. etc.] длина = 11
год в [1960 : 2014]
месяц в [1:12]
зона (бассейн) [1 : 16000]

Вариант 1

Мой первый вариант - создать отдельную таблицу для каждого индикатора и сохранить данные следующим образом:

|  ID   | basin_id | temperature | unit | year | month | temporal_resolution |
|-------|----------|-------------|------|------|-------|---------------------|
|     1 |        1 |        42.1 | k   | 2000 |     1 | month               |
|     2 |        2 |        1.87 | k   | 2000 |     1 | month               |
|    .. |       .. |          .. | ..   |   .. |    .. | ..                  |
| 11001 |        1 |        40.3 | m3   | 2000 |     2 | month               |
| 11002 |        2 |         2.3 | m3   | 2000 |     2 | month               |

Опция 2

, а второй вариант создает вертикальную таблицу:

|  ID   | basin_id |  indicator  | value | unit | year | month | temporal_resolution |
|-------|----------|-------------|-------|------|------|-------|---------------------|
|     1 |        1 | temperature |  42.1 | k   | 2000 |     1 | month               |
|     2 |        2 | temperature |  1.87 | k   | 2000 |     1 | month               |
|    .. |       .. | ..          |    .. | ..   |   .. |    .. | ..                  |
| 11001 |        1 | precipitation |  40.3 | m3   | 2000 |     2 | month               |
| 11002 |        2 | precipitation |   2.3 | m3   | 2000 |     2 | month               |

Мой вопрос заключается в том, рекомендуется ли разделение имени и значения индикатора или не следует использовать.Если данные хранятся по вертикали, общее количество строк будет приблизительно.16000 * 11 * 12 * 55 = 116 160 000, что, я не уверен, очень управляемо.

Вариант 3

РЕДАКТИРОВАТЬ: поскольку число индикаторов ограничено (12 или около того), вертикальная таблицаструктура не требуется.Третий вариант - объединение различных таблиц индикаторов в нечто вроде:

|  ID   | basin_id | temperature_k | precipitation_m | …  | riverdischarge_m3 | year | month | temporal_resolution |
|-------|----------|---------------|-----------------|----|-------------------|------|-------|---------------------|
|     1 |        1 |          42.1 |            42.1 | …  |              42.1 | 2000 |     1 | month               |
|     2 |        2 |          42.1 |            42.1 |    |              42.1 | 2000 |     1 | month               |
|    .. |       .. |            .. |              .. | .. |                .. |   .. |    .. | ..                  |
| 11001 |        1 |          42.1 |            42.1 | .. |              42.1 | 2000 |     2 | month               |
| 11002 |        2 |          42.1 |            42.1 | .. |              42.1 | 2000 |     2 | month               |

В результате row_count равен 16000 * 55 * 12 = 10 560 000

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Поскольку мы тоже проводим морские исследования, я понимаю ваши потребности (возможно, это данные, полученные из CTD).По моему опыту:

  • Вместо поля даты \ даты / времени использование отдельных полей года, месяца, дня и часа имело значение (разрешение почти никогда не опускалось ниже часа).
  • Дляразные наборы проб использовали другой набор данных, приходящий в формате текстового файла с разделителями (строки заголовка вверху).Импортируя это и позже делая некоторые проверки, преобразования, использующие поле для каждого параметра, имели смысл.
  • OTOH были случаи, когда модели требовалось слишком много данных того же типа, я наблюдал, используя неТрадиционные способы хранения данных оказались намного быстрее.То есть: в пределах диапазона дат (скажем, последние 5 лет) определенный параметр измеряется с фиксированным периодом секунды.Это 86400 измерений этого параметра в день.Умножьте это на 5 лет, и вы получите около 158 миллионов значений, и это только для местоположения.Если вам нужно сохранить это для 20 местоположений, вам потребуется более 3 миллиардов строк данных, если вы делаете это традиционными способами.Если бы это не повлияло и на хранилище, я бы сказал, что это проблема ETL и последующего анализа.При традиционном подходе, если вы сделаете это:

    LocationID (int), Datetime (который будет увеличиваться в секунду), Value

    это выглядит невинно, но только объем хранилища будет более 30 Гб.Поэтому вместо этого я выбрал другой подход и сохранил:

    LocationId, date (не datetime), oneDayWorthValues ​​(в двоичном виде, с фиксированной скоростью в секунду, если диапазон значений умещается в 2 байта, то каждая строка имеет ровно 86400 * 2 байта двоичных данных) - база данных, которую я тогда использовал, не имела типа данных массива.

Только мои 0,05 цента, но, возможно, стоит, если вы также сделаете что-то подобное (редко с данными о воде).

0 голосов
/ 23 мая 2018

Это пример моделирования наследования в реляционной базе данных.

У вас есть абстрактная сущность - "наблюдение" - со свойствами zone, year и month, конкретные сущности "Temperature_observation" с атрибутом "температура" и сущность "осадки" с "кубической"метров».

Этот ТАК вопрос описывает доступные варианты - ни один из них не является особенно чистым.Ваш вариант 1 - «таблица на подкласс».

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

Вариант 3 - «наследование одной таблицы».Это общий шаблон проектирования, который обычно работает, если у вас ограниченное количество подклассов;как только вы получаете много подклассов, это становится довольно трудно понять.

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

Если вы хотите использовать базу данных для более сложных запросов -

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

какова средняя температура в бассейнах, где количество осадков составляет не менее х?

  • , тогда вы можете пожелать "читабельность" своих запросов.

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

Варианты 2 и 3 требуют самостоятельных объединений, которые могут стать довольно сложными и трудными для чтения по мере усложнения условий.

Например, вопрос what's the average temperature in basins where precipitation is at least x? в варианте 1:

select avg(temperature)
from temperature_facts
where basin_id in 
  (select basin_id
   from precipitation_facts
   where precipitation > ?)

В варианте 2 это становится:

select avg(value)
from   facttable
where  indicator = 'temperature'
and    basin_id in 
  (select basin_id
   from fact_table
   where value > ?
   and indicator = 'precipitation')

В варианте 3 это что-то вроде

select avg(temperature)
from fact_table
where basin_id in 
  (select basin_id
  from fact_table
  where precipitation > ?)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...