Структурирование таблицы разреженных данных + ORM (+ NoSQL?)

Работая над программным обеспечением для термодинамического моделирования (на C++), мне нужно сохранять свойства жидкости при разных температурах. Эти точки данных используются для построения простой функции интерполяции, чтобы оценить значения свойств также при температурах, для которых у нас нет полных экспериментальных данных.

Жидкость просто идентифицируется по ее названию и концентрации (%) (последнее часто не имеет значения). Если вам интересно, интерес представляют четыре свойства: массовая плотность, динамическая вязкость, удельная теплоемкость и теплопроводность. Для любого другого намерения и цели это всего лишь 4 числовых свойства, назовите их A, B, C и D. Таким образом, функция для конкретной жидкости выглядит примерно так: (A,B,C,D) = f(T), где T — температура.

В настоящее время это база данных SQLite3, и таблица жидкостей выглядит так:

+----+-------+---------------+
| id | name  | concentration |
+====+=======+===============+
|  1 | Water |           100 |
+----+-------+---------------+
|  2 | ..... |           ... |

И есть таблица свойств:

+----------+-------------+---------+-----------+--------------+----------+
| fluid_id | temperature | density | viscosity | conductivity | capacity |
+==========+=============+=========+===========+==============+==========+
|        2 | 373.15      | 1045.48 | 0.412     | 1.415        | 0.845    |
|        3 | 273.15      | 1105.0  | 2.113     | 0.4688       | 0.849    |
|        3 | 283.15      |         | 1.678     | 0.4859       | 0.8503   |
|        3 | 293.15      | 1098.0  | 1.353     | 0.5015       | 0.5833   |
|        3 | 303.15      |         | 1.08      | 0.5164       |          |
|        3 | 313.15      | 1090.0  | 0.893     | 0.532        | 0.8561   |
|        3 | 323.15      |         | 0.748     | 0.5432       |          |
|        3 | 333.15      | 1080.0  | 0.644     | 0.5543       | 0.8577   |
|        3 | 343.15      |         | 0.563     | 0.564        |          |
|        3 | 353.15      | 1068.0  | 0.499     | 0.5722       | 0.8612   |
|        3 | 363.15      |         | 0.44      | 0.5796       |          |
|        3 | 373.15      | 1054.0  | 0.39      | 0.5856       |          |
+----------+-------------+---------+-----------+--------------+----------+

Вставка данных вручную для тестирования была в порядке. Это также будет интуитивно понятным интерфейсом для графического интерфейса редактора Fluid Editor.

Однако в коде интерполяция выполняется отдельно для каждого свойства. Более того, поскольку я не могу использовать значения NULL, не все температуры (строки) относятся ко всем свойствам. Чтобы адаптировать вещи с точки зрения кода, я создал четыре идентичных представления — по одному для каждого свойства. Например:

+----+-----------+---------------+-------------+-------+
| id |   name    | concentration | temperature | value |
+====+===========+===============+=============+=======+
|  2 | Sea Water |            22 | 373.15      | 0.412 |
|  3 | Sea Water |            14 | 273.15      | 2.113 |
|  3 | Sea Water |            14 | 283.15      | 1.678 |
|  3 | Sea Water |            14 | 293.15      | 1.353 |
|  3 | Sea Water |            14 | 303.15      | 1.08  |
|  3 | Sea Water |            14 | 313.15      | 0.893 |
|  3 | Sea Water |            14 | 323.15      | 0.748 |
|  3 | Sea Water |            14 | 333.15      | 0.644 |
|  3 | Sea Water |            14 | 343.15      | 0.563 |
|  3 | Sea Water |            14 | 353.15      | 0.499 |
|  3 | Sea Water |            14 | 363.15      | 0.44  |
|  3 | Sea Water |            14 | 373.15      | 0.39  |
+----+-----------+---------------+-------------+-------+

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

Я даже рассматривал возможность переноса этого набора данных в решение NoSQL (например, MongoDb), но не мог придумать, как решить проблему двойной перспективы.

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

В противном случае я хотел бы услышать ваши мысли и рассмотреть любой другой подход, который вы могли бы предложить. Я что-то упускаю? Как насчет избыточности ключей (жидкости и температуры), которая может возникнуть при разделении таблицы? Кроме того, это может быть интересно тем, у кого есть ограничения.


person oranja    schedule 12.11.2015    source источник


Ответы (1)


Каждая таблица со значением NULL, указывающим на «отсутствующее» («неизвестное» или «неприменимое») значение, соответствует схеме, в которой отбрасывается столбец, допускающий NULL, и вводится другая таблица с некоторым (супер) ключом оригинала и содержащая только строки, отличные от NULL в этом столбце в Это.

Нули поддерживают более легкое одновременное чтение человеком этих отдельных таблиц с одинаковыми (супер) ключами. Но они усложняют все остальное, включая значение таблицы (критерий/предикат, по которому строка входит или не входит) , следовательно, базовый дизайн и состав запроса. Обычно мы как можно скорее удаляем любые значения NULL, которые не вставлены в ключ для отображения вместе с ним в окончательном выводе. (Например, OUTER JOIN часто используется идиоматически, чтобы ввести, а затем удалить NULL, чтобы выразить NULL-free EXCEPT/MINUS.) Мы используем значения отдельных таблиц как при выражении значения таблицы с NULL, так и в значении запросов, использующих ее. Мы извлекаем отдельные таблицы из объединенного представления NULL для практически любой обработки.

Простое реляционное решение — это отдельные таблицы. Традиция SQL для одной таблицы. Другие обоснования SQL - это сокращение JOIN от объединения таблиц. Но это только для окончательного удобочитаемого вывода! Чтобы обработать одну таблицу, вам все равно придется извлекать отдельные представления.

PS
Относительно «избыточности ключей (жидкости и температуры), которая может возникнуть при разделении таблицы»: нет «избыточности" в том, что одно и то же значение (подстроки) появляется более одного раза в столбце, таблице или базе данных. Избыточность возникает, когда две базовые таблицы или строки делают одно и то же утверждение. Строка, подставленная в критерий/предикат, дает утверждение/предложение; существующая строка утверждает свое, а отсутствующая строка утверждает НЕ свое; таблица (предложение) утверждает конъюнкцию утверждений присутствующих и отсутствующих строк. (И база данных (предложение) утверждает конъюнкцию предложений своих таблиц.) Более того, избыточность не обязательно плоха; всегда существует инженерный компромисс между временем, пространством и сложностью.

PPS
ORM имеют представления: отложенная или отложенная оценка запроса. Поскольку впоследствии вы можете использовать такой запрос внутри другого, он действует точно так же, как представление. Это именованное представление запроса на языке запросов ORM, а не на языке запросов СУБД. Это может быть как для команды обновления (когда это возможно), так и для запроса. Это зависит от СУБД/ORM. Однако обновление представления в основном удобно, поскольку оно всегда может быть выражено в терминах обновлений составляющих таблиц.

person philipxy    schedule 14.11.2015
comment
Таким образом, благодаря вашему важному вкладу кажется, что я делаю что-то в обратном порядке (с точки зрения реляционной модели). Я рад, что спросил достаточно рано. Единственная проблема, которая не затрагивается здесь напрямую, — это избыточность ключей (жидкости и температуры), которая может возникнуть при разделении таблицы. Однако, после прочтения немного о дебатах относительно маркеров NULL, теперь мне кажется ошибочным сохранять таблицу в том виде, в котором она есть. - person oranja; 15.11.2015
comment
Что касается представлений и ORM, в случае SQLite, который поддерживает только представления только для чтения, отложенная оценка может быть аналогична представлениям. Лично я предпочитаю, чтобы представления были доступны только для чтения. Тем не менее, другие RDBM, а также реляционная модель поддерживают операции записи в представлениях. Разве отложенная оценка здесь не работает? - person oranja; 15.11.2015
comment
(1) Спасибо за отличные ответы. (2) Я согласен с тем, что во многих отношениях представление — это просто удобство. Однако в целом я считаю, что тщательно разработанное представление может служить полезной абстракцией поверх (также тщательно разработанной) схемы. В таких случаях я бы счел неприемлемым нарушение абстракции ORM. Не всегда программист и администратор баз данных — одно и то же. В любом случае, здесь это не входит в наши обязанности. (3) Какое последнее предложение? О чужих ограничениях? Это относится к абзацу выше. Я оставлю это на усмотрение других, чтобы разрешить особые ограничения в обсуждении, если таковые имеются. - person oranja; 19.11.2015