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

Дана дорогая функция из n переменных, которая возвращает скалярное значение:

f(x1, x2, ..., xn) = y

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

(Связано, но под другим углом зрения: какой тип модели данных моделирует параметры и результаты?)

2 ответа

Решение

В некоторой степени в зависимости от значения 'n', вы, вероятно, можете смоделировать его следующим образом. Предположим, что значение n равно 137.

create table expensive_function_of_n_vars (
  x1 integer not null,
  x2 integer not null,
  ...
  x137 integer not null,
  primary key (x1, x2, ..., x137),
  result integer not null
);

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

Это предполагает, что каждый столбец имеет какое-то значение. То есть, я предполагаю, что в реальной проблемной области каждый из этих столбцов имеет имя, более значимое, чем "x3".

Например, в статье, на которую вы ссылались, OP использует "высоту", "ширину" и "глубину". В некоторых приложениях эти измерения не являются взаимозаменяемыми - вы можете однозначно определить, какое измерение на объекте реального мира - это высота, а что ширина, а какая глубина. (Одним из примеров может быть транспортный контейнер на поддоне, где высота очевидна, ширина - это кромка, под которой должен укладываться вилочный погрузчик, а глубина - оставшееся измерение.) В других приложениях они взаимозаменяемы, что означает, что вы ' обязан найти "дубликаты" первичных ключей, таких как {2, 3, 5} и {2, 5, 3}. В подобных случаях вам может потребоваться упорядочить аргументы от низшего к высшему и использовать ограничения CHECK(), чтобы убедиться, что они упорядочены.

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

Во-первых, СУБД не обязательно является лучшим выбором для управления запоминанием. Этот подход оправдан только в том случае, если число результатов слишком велико для размещения в ОЗУ или если результаты необходимо сохранять в течение длительного периода времени или их необходимо повторно использовать для нескольких, возможно, одновременных клиентов.

Для каждой функции создайте отдельную таблицу со столбцами, которые соответствуют входам и результатам функции. Создать ПК на входах.

Перед оценкой функции (на value1, value2, value3...), сделайте:

SELECT result
FROM function_table
WHERE
    input1 = :value1
    AND input2 = :value2
    AND input3 = :value3
    ...

( : обозначает связанный параметр, некоторые СУБД могут использовать другой префикс)

  • Если вы получите результат, используйте его. Функция была оценена ранее, и вы можете пропустить оценку на этот раз.
  • Если вы не получите никакого результата (т. Е. Ноль строк), оцените функцию и сохраните входные данные и результат для последующего повторного использования. Попробуйте сделать эту INSERT в фоновом потоке, чтобы можно было использовать результат в основном потоке, не дожидаясь базы данных.

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

Кроме того, рассмотрите возможность кластеризации таблицы (если ваша СУБД поддерживает ее), чтобы получить результат непосредственно из структуры B-Tree и избежать необходимости поиска кучи таблиц.

Другие вопросы по тегам