【问题标题】:SQL Calculated Field EfficiencySQL 计算字段效率
【发布时间】:2018-04-09 02:13:34
【问题描述】:

我的数据库将 GUID 作为主键,这样做是为了在多个系统之间强制执行唯一性。 (是的,我知道每个表开销每行 16 个字节,除了公司选择之外还有其他选择)

为了让表格更友好一点,我添加了计算字段,所以如果你选择类似

SELECT * FROM Products

您不仅会获得具有外键的列,还会获得与其关联的友好字段。

例如 CompanyGUID(存储字段)、CompanyName(计算字段)

计算字段通过标量函数运行,例如:

CREATE FUNCTION [mySchema].[udf_CompanyNameFromGUID] (@GUID UNIQUEIDENTIFIER)
RETURNS NVARCHAR(MAX)
AS
    BEGIN
        DECLARE @Return NVARCHAR(MAX)
        SELECT  @Return = CompanyName
        FROM    mySchema.Companies
        WHERE   CompanyGUID = @GUID
        RETURN @Return
    END

我应该指出,这些查找总是针对主键/聚集索引,所以我可以尽可能快地单独查找。

现在,虽然这在我们追溯问题时有很多优势,并且在我们查询大表时对主要使用效率没有任何影响(未查询计算字段,因此没有影响),但确实需要同时进行查找。我不想牺牲我正在查找的额外数据,也不想将其直接存储在表中(浪费数据并且需要维护)。我考虑过为每个表构建视图,但这似乎有点过头了,我宁愿不必加倍努力。

我确定我不是唯一这样工作的人,所以我想知道是否有人有更有效的方法来做到这一点?这些字段只供直接查看数据库的人使用,所有存储过程等都是用索引链接等完全编码的,所以主要运行效率很好,只是调试。问题不大,但如果有更好的解决方案,我很乐意听到。

提前致谢。

【问题讨论】:

  • 所以您使用标量函数将计算列添加到表中以使开发人员更容易?他们不应该只学习如何编写连接吗?似乎输入该连接会比您尝试做的工作更少。
  • 老实说,我在这里跟踪数据的次数和其他任何人一样多,越直观越好。所有花时间在数据上的人(和一个女孩)都非常有能力编写连接,只是每次看时都必须一遍又一遍地做。我宁愿做一次,不必再做一次。
  • 或者编写一个视图来为它们进行连接。将其包装在标量 UDF 中将很快保证性能不佳。它将强制所有查找使用 RBAR 嵌套循环,并且存在与标量 UDF 相关的各种问题。
  • 是的,我在以前的环境中使用了视图方法,但试图不在这里添加膨胀。我们之前使用它是因为我们允许客户访问我们为他们的 SSRS 报告预先优化的视图模式。我们最不想要的就是客户端尝试编写查询,无论我们的数据库多么紧凑。

标签: sql-server performance calculated-columns calculated-field


【解决方案1】:

我的建议:

  1. 对于companyGUID 列,您可以生成和使用NEWSEQUENTIALID 而不是NEWID,它可以减少碎片。并提高索引性能。
  2. 您可以通过添加 PERSISTED 选项使 CompanyName 列保持不变。

【讨论】:

  • OP 声明他们使用 guid 作为确保跨系统唯一性的一种方式。 sequenceid 将使这成为不可能。实际上,uniqueidentifier 对于主键来说并不可怕,但作为聚集索引它不是一个好的选择。正如你所说,碎片变得疯狂。
  • RE: 2 他们将无法使这种情况持续存在。它不是确定性的。
  • 我曾考虑过持久化列,这确实会提高性能,但也会影响所需的存储量。虽然不是很大,但这些字段仅用于调试或跟踪数据。很高兴看到有人和我走同样的路。感谢您的选择。
【解决方案2】:

您的主要性能问题不是由查找引起的,而是由于使用了SCALAR FUNCTION

对每一行调用标量函数,它本身不是免费的,而是乘以行数,对性能有很大影响。

可能view 是您的解决方案:它不需要任何额外的空间,因为它只是在您使用视图时将扩展的代码,并且在视图中只需使用mySchema.Companies 加入您的表:

create view dbo.MyView as
select * -- put here your columns of interest including CompanyName
from dbo.YourTable
     join  mySchema.Companies
         on CompanyGUID = @GUID;

【讨论】:

  • 是的,我在以前的环境中使用了视图方法,但试图不在这里添加膨胀。我们之前使用它是因为我们允许客户访问我们为他们的 SSRS 报告预先优化的视图模式。我们最不想要的就是客户端尝试编写查询,无论我们的数据库多么紧凑。
  • 对不起,我不明白你的问题。如果您不希望您的客户直接使用该表,只需拒绝对其进行选择,同时保留对视图的选择权限
  • 客户端已经被拒绝访问,这只是一个例子。这仅供我们内部使用,主要用于非dba需要跟踪数据问题时。为什么我看不到产品,为什么我得到这个价格。虽然我认为让他们编写自己的查询是公平的,但如果我能想出更好的选择,我宁愿让他们更有效率地花费时间。 +1 的答案,但不是我想要的。非常感谢。
猜你喜欢
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多