在关系数据库中应该使用什么样的表结构来存储已记忆的函数参数和结果?

时间:2012-06-21 22:53:44

标签: database-design memoization

给定n个变量的昂贵函数,返回标量值:

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

如果我想在关系数据库中记住这个函数,我应该使用什么样的表结构,以及适用哪种数据建模方法?

(相关但从不同角度:What kind of data model models function parameters and results?

2 个答案:

答案 0 :(得分:1)

在某种程度上取决于'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使用“height”,“width”和“depth”。在某些应用中,这些尺寸不可互换 - 您可以明确地识别真实世界物体上的哪个尺寸是高度,即宽度,哪个是深度。 (一个例子可能是托盘上的集装箱,高度明显,宽度是叉车预计适合的边缘,深度是剩余尺寸。)在其他应用中,它们是可互换的,这意味着你'我很容易找到“重复的”主键,如{2,3,5}和{2,5,3}。在这种情况下,您可能希望将参数从最低到最高排序,并使用CHECK()约束来确保它们是有序的。

这只是直接规范化,但需要注意的是,在这种情况下,你在6NF中开始,我认为,所以没有太多事情要做。

答案 1 :(得分:1)

首先,DBMS不一定是处理memoization的最佳选择。只有当结果数量太大而无法容纳在RAM中或者结果需要在很长一段时间内保持或需要在多个(可能是并发的)客户端之间重用时,这种方法才是合理的。

对于每个函数,创建一个单独的表,其中的列对应于函数输入和结果。在输入上创建PK。

在评估功能之前(value1value2value3 ...),请执行以下操作:

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

:表示绑定参数,某些DBMS可能使用不同的前缀)

  • 如果您得到结果,请使用它。之前评估过该功能,您可以跳过此次评估。
  • 如果没有结果(即零行),请评估函数并存储输入和结果以供以后重用。考虑在后台线程上执行此INSERT,这样您就可以继续在主线程上使用结果而无需等待数据库。

通过为每个函数使用带有绑定参数的单独表和静态定制查询,您可以利用query preparation来获得更好的性能。

另外,考虑clustering the table(如果您的DBMS支持它),直接从B-Tree结构获取结果,并避免需要进行表堆查找。