在存储过程后面抽象数据库的优点和缺点是什么?

时间:2012-07-05 10:09:17

标签: sql api postgresql database-design

在工作中,我们目前有一个PostgreSQL数据库,我们通过一些Perl绑定访问它来访问数据库并编组对Perl类型的响应。这很好用,但由于种种原因,我们对Perl感到不满。我们一直在考虑的一个选择是将此API中的大部分工作作为plpgsql存储过程移至数据库本身。

简要示例

例如,我们可能在数据库中有以下内容:

-- This matches our 'Entity::Artist' object
CREATE TYPE loaded_artist (
  artist_id uuid,
  revision_id integer,
  artist_tree_id integer,
  name text,
  sort_name text,
  artist_type_id integer,
  -- etc
);

-- This gets the latest 'master' version of an artist and joins in basic data
-- from the artist tree
CREATE FUNCTION get_latest_artist_by_mbid(in_mbid UUID)
RETURNS SETOF loaded_artist AS $$
  BEGIN
    RETURN QUERY
    SELECT
      artist_id, revision_id, artist_tree_id, name.name,
      sort_name.name AS sort_name, artist_type_id
    FROM artist
    JOIN artist_revision USING (artist_id)
    JOIN artist_tree USING (artist_tree_id)
    JOIN artist_data USING (artist_data_id)
    WHERE artist.master_revision_id = revision_id
      AND artist_id = in_mbid;
  END;
$$ LANGUAGE 'plpgsql';

现在,我们当前的Perl API可以简化为以下内容:#And in Perl

package Data::Artist;
sub get_latest_by_mbid {
    my ($self, $mbid) = @_;
    return $self->new_from_row(
        $self->sql->select_single_row_hash(
            'SELECT * FROM get_latest_artist_by_mbid(?)',
            $mbid));
}

这是明智的吗?

从表面上看,我喜欢这个。我们:

  • 离开Perl,但不要使用其他语言。这意味着我们可以将我们的实际应用程序移动到Python /将来的任何内容,并且我们的大多数API已经完成。
  • 由于指定RETURNS SETOF loaded_artist
  • 等内容,从PostgreSQL获得额外的类型安全性
  • 仍然通过PGTAP进行单元测试和填充。

有一些缺点:

  • 我们现在必须替换数据库中的函数,因此可能会降低开发周期。不是世界末日,但这有效地将“编译”步骤引入我们之前不存在的工作流程中。
  • 版本控制可能更难,但肯定有这样做的方法

有人做过这样的工作吗?你会鼓励它,还是充满危险?


脚注:关于我们案例的更多信息

这是一个开源网站。我们分发数据库的转储,供人们导入PostgreSQL数据库。我们没有计划很快离开PG,所以数据库无关的决定并不真正适用于我们。我们是一个非常小的团队(2个付费开发人员,更多的开源贡献者),这使我们在部署策略方面非常灵活。

2 个答案:

答案 0 :(得分:4)

优点:

  • 数据库架构/布局/存储更改完全隐藏在应用程序之外;
  • 您有一个统一的API来处理数据库;
  • 您可以对数据库中完成的所有操作进行大量日志记录,包括所有SELECT个查询。

缺点:

  • 增加了对优秀DBA的需求;
  • 数据库开发人员需要更多地了解数据库如何处理数据以及数据库端程序如何工作;
  • 数据库端和应用程序端团队之间需要更多协调;
  • ORM集成的困难;
  • 使用存储过程限制了数据库的优化可能性,一些查询(特别是报告)会产生性能问题,最好使用视图,因为优化器可以将谓词压缩到视图中并正确使用索引。

最佳组合是在数据库端实现业务逻辑,而不仅仅是包装函数。

可以使用模式版本控制。在配置表中对数据进行版本化更加棘手。在我参与的一个项目中,这是通过外部工具(基于perl)完成的,该工具为我们处理这部分:

  • 首先将数据加载/提取到中间表中;
  • 然后分析RI约束和所有可能的违规行为;
  • 在将其加载到实时表格之前可以进行数据处理;
  • 可以一次性定义和提取产生多个表的业务对象;
  • 存在多种处理匹配实体的方法,如:覆盖,合并,复制。

我们正在对提取文件进行版本控制(这是一个普通的SQL),并在安装脚本中有一个特殊步骤来加载新配置。

答案 1 :(得分:0)

到便携性:

  • 通过使用存储过程,您可以在客户端上获得更多可移植性,正如您已经注意到的那样。
  • 通过使用存储过程,您在服务器上更具可移植性(您可以更轻松地移动到其他DBMS)。