7

我正在 SQL Server 2008 中为一些报告建立一个新数据库,并且有许多与这些数据相关的常见业务规则进入不同类型的报告。目前,这些规则大多结合在更大的程序程序中,使用一种遗留语言,我正试图将其转移到 SQL。我正在争取灵活地从这些数据中实现报告,比如 SAS 中的一些报告,C# 中的一些报告等。

我目前的方法是分解这些通用规则(通常是非常简单的逻辑)并将它们封装在单独的 SQL UDF 中。性能不是问题,我只想使用这些规则在一种报告“快照”中填充静态字段,然后可以使用它以您想要的任何方式进行报告。

就理解每个规则在做什么(以及维护规则本身)而言,我喜欢这种模块化方法,但我也开始有点担心维护也可能成为一场噩梦。有些规则取决于其他规则,但我真的无法摆脱这一点 - 这些东西相互依赖......这就是我想要的......我想?;)

数据库中的这种模块化方法是否有更好的方法?我是在正确的轨道上,还是我在考虑太多应用程序开发的心态?

4

5 回答 5

2

在某些时候,UDF 的广泛使用将开始导致性能问题,因为它们是针对结果集中的每一行执行的,并且优化器中的逻辑模糊不清,从而难以使用索引(即,我真的不明白如何不能提高性能)一个问题,但您最了解自己的要求)。对于某些功能,它们很棒;但要谨慎使用它们。

于 2010-01-28T22:16:30.927 回答
2

将逻辑保留在数据库端几乎总是正确的做法。

正如您在问题中提到的,大多数业务规则都涉及非常简单的逻辑,但它通常处理大量数据。

数据库引擎是实现该逻辑的正确选择,因为首先,它将数据保持I/O在最低限度,其次,数据库执行大多数数据转换的效率更高。

前段时间我就这个话题写了一篇非常主观的博文:

附带说明: aUDF与存储过程不同。

AUDF是一个在查询中由 callable 设计的函数,因此它只能执行非常有限的可能操作子集。

你可以做的更多是存储过程。

更新:

在您给出的示例中,就像更改计算“派生字段”的逻辑一样UDF,计算该字段是可以的。

但是(以防万一)当性能成为问题时(相信我,这会比人们想象的要快得多),使用基于集合的操作转换数据可能比使用UDFs.

在这种情况下,您可能希望创建一个视图、一个存储过程或一个表值函数返回一个结果集,该结果集将包含更有效的查询,而不是限制自己更新UDFs(它们是基于记录的)。

一个例子:您的查询有类似“用户分数”之类的东西,您觉得可能会发生变化并将其包装成UDF

SELECT  user_id, fn_getUserScore(user_id)
FROM    users

最初,这只是表中的一个普通字段:

CREATE FUNCTION fn_getUserScore(@user_id INT) RETURNS INT
AS
BEGIN
        DECLARE @ret INT
        SELECT  user_score
        INTO    @ret
        FROM    users
        WHERE   user_id = @user_id
        RETURN @ret
END

,然后您决定使用其他表中的数据来计算它:

CREATE FUNCTION fn_getUserScore(@user_id INT) RETURNS INT
AS
BEGIN
        DECLARE @ret INT
        SELECT  SUM(vote)
        INTO    @ret
        FROM    user_votes
        WHERE   user_id = @user_id
        RETURN @ret
END

这将使引擎NESTED LOOPS在任何一种情况下都使用效率最低的算法。

但是,如果您创建了一个视图并像这样重写了基础查询:

SELECT  user_id, user_score
FROM    users

SELECT  user_id, SUM(vote) AS user_score
FROM    users u
LEFT JOIN
        user_votes uv
ON uv.user_id = u.user_id

,这将为引擎提供更广阔的优化空间,同时仍保持结果集结构并将逻辑与表示分离。

于 2010-01-28T22:17:29.657 回答
1

我想说你走在正确的轨道上——随着越来越复杂,sql 过程可能会迅速失控,将共享的、重复的逻辑片段封装到 UDF 中是解决这个问题的完全合适的解决方案。

我经常将仅在该过程中使用的 sql 过程中的逻辑封装到命名良好的 UDF 中,以提高可读性。

看看这篇关于 UDF 的 MSDN 文章——也许它会给你一些关于它们的使用的更多想法?

如果您打算大量使用 UDF,则需要注意各种性能注意事项 - 例如标量与表 UDF 的性能以及 CLR UDF 的可能优势。

于 2010-01-28T22:17:06.753 回答
1

SQL 是基于集合的,并且在应用模块化方法时固有地表现不佳。
函数、存储过程和/或视图——它们都抽象了底层逻辑。当您使用使用相同表的两个(或更多)函数/等时,性能问题就会发挥作用。这意味着当可以使用一个查询时,两个查询会生成同一张表。

多个函数的使用对我来说表明数据模型非常“灵活”。对我来说,这意味着有问题的数据输入和整体列/表定义。需要函数/等,因为数据库将允许存储任何内容,这意味着坏数据的可能性非常高。我宁愿努力始终拥有良好/有效的数据,而不是事后努力打击现有的不良数据。

数据库是包含此逻辑的地方。它比应用程序代码更快,最重要的是 - 集中化以最大限度地减少维护。

于 2010-01-28T22:24:21.550 回答
0

如果您对构建用于报告的数据仓库感兴趣,您会尝试尽可能多地将其放入 ETL 的转换部分,以便您的报告 SQL 由工具和用户等能够生成的简单语句组成。

SSIS 是非常强大的 ETL 工具,它附带 SQL Server 来处理这类事情。

于 2010-01-28T22:17:17.927 回答