加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

sql-server – SQL Server – 处理嵌套的非确定性视图堆栈中字符

发布时间:2021-01-08 07:30:52 所属栏目:MsSql教程 来源:网络整理
导读:在分析数据库时,我遇到了一个视图,该视图引用了一些非确定性函数,每个连接在此应用程序池中每分钟访问1000-2500次.视图中的简单SELECT产生以下执行计划: 这似乎是一个复杂的计划,一个不到一千行的视图,每隔几个月就会看到一行或两行.但随着以下其他纪念活

在分析数据库时,我遇到了一个视图,该视图引用了一些非确定性函数,每个连接在此应用程序池中每分钟访问1000-2500次.视图中的简单SELECT产生以下执行计划:




这似乎是一个复杂的计划,一个不到一千行的视图,每隔几个月就会看到一行或两行.但随着以下其他纪念活动,情况会变得更糟:

>嵌套视图是非确定性的,因此我们无法对它们编制索引
>每个视图引用多个UDF来构建字符串
>每个UDF都包含嵌套的UDF,以获取本地化语言的ISO代码
>堆栈中的视图使用从UDF返回的其他字符串构建器作为JOIN谓词
>每个视图堆栈都被视为一个表,这意味着每个视图堆栈都有INSERT / UPDATE / DELETE触发器写入基础表
>视图上的这些触发器使用CURSORS EXEC存储过程,这些过程引用了更多这些字符串构建UDF.

这对我来说似乎很糟糕,但我只有几年的TSQL经验.它也变得更好!

看起来开发人员认为这是一个好主意,做了所有这些,以便存储的几百个字符串可以基于从特定于模式的UDF返回的字符串进行转换.

这是堆栈中的一个视图,但它们都同样糟糕:

CREATE VIEW [UserWKStringI18N]
AS
SELECT b.WKType,b.WKIndex,CASE
       WHEN ISNULL(il.I18NID,N'') = N''
       THEN id.I18NString
       ELSE il.I18nString
       END AS WKString,N'') = N''
       THEN id.IETFLangCode
       ELSE il.IETFLangCode
       END AS IETFLangCode,dbo.User3StringI18N_KeyValue(b.WKType,N'WKS') AS I18NID,dbo.UserI18N_Session_Locale_Key()  AS IETFSessionLangCode,dbo.UserI18N_Database_Locale_Key() AS IETFDatabaseLangCode
FROM   UserWKStringBASE b
LEFT OUTER JOIN User3StringI18N il
ON    (
il.I18NID       = dbo.User3StringI18N_KeyValue(b.WKType,N'WKS')
AND il.IETFLangCode = dbo.UserI18N_Session_Locale_Key()
)
LEFT OUTER JOIN User3StringI18N id
ON    (
id.I18NID       = dbo.User3StringI18N_KeyValue(b.WKType,N'WKS')
AND id.IETFLangCode = dbo.UserI18N_Database_Locale_Key()
)
GO

这就是为什么UDF被用作JOIN谓词的原因. I18NID列通过连接:STRING [ID | ID ]

在测试这些过程中,视图中的一个简单的SELECT返回~309行,并执行900-1400ms.如果我将字符串转储到另一个表中并在其上打一个索引,则相同的select将在20-75ms内返回.

所以,长话短说(我希望你对这种愚蠢行为表示赞赏)我希望成为一名优秀的撒玛利亚人,并为99%运行该产品的客户重新设计并重新编写此内容,而这些客户并未使用任何本地化 – 即使英语是第二/第三语言,即使用户也应使用[en-US]语言环境.

由于这是一个非正式的黑客攻击,我想到的是:

>创建一个新的String表,其中填充了原始基表中干净连接的数据集
>索引表格.
>在堆栈中创建一组替换的顶级视图,其中包括WKType和WKIndex列的NVARCHAR和INT列.
>修改引用这些视图的少数UDF,以避免某些连接谓词中的类型转换(我们最大的审计表是500-2,000M行,并在NVARCHAR(4000)列中存储INT,用于连接WKIndex列( INT).)
> Schemabind的观点
>向视图添加一些索引
>使用set logic而不是游标在视图上重建触发器

现在,我的实际问题:

>是否有通过视图处理本地化字符串的最佳实践方法?
>使用UDF作为存根有哪些替代方案? (我可以为每个架构所有者编写一个特定的VIEW并对该语言进行硬编码,而不是依赖于各种UDF存根.)
>通过完全限定嵌套UDF然后对视图堆栈进行模式绑定,可以简单地使这些视图成为确定性的吗?

解决方法

看一下给定的代码,我们可以说,

>首先,这不应该是一个视图,但它应该是一个存储过程,因为它不仅仅是从表中读取,而是使用UDF.
>其次,不应经常为同一列调用UDF.在这里,它在select中被调用一次

,N'WKS') AS I18NID

第二次加入

.IETFLangCode = dbo.User3StringI18N_KeyValue(b.WKType,N'WKS')

可以在临时表中生成值或使用CTE(公用表表达式)在连接发生之前首先获取这些值.

我已经生成了一个样本USP,它将提供一些改进:

CREATE PROCEDURE usp_UserWKStringI18N
AS
BEGIN
    -- Do operation using UDF 
    SELECT b.WKType,dbo.UserI18N_Session_Locale_Key() AS IETFSessionLangCode,dbo.UserI18N_Database_Locale_Key() AS IETFDatabaseLangCode
    INTO #tempTable
    FROM UserWKStringBASE b;

    -- Now final Select
    SELECT b.WKType,CASE 
            WHEN ISNULL(il.I18NID,N'') = N''
                THEN id.I18NString
            ELSE il.I18nString
            END AS WKString,N'') = N''
                THEN id.IETFLangCode
            ELSE il.IETFLangCode
            END AS IETFLangCode,b.I18NID,b.IETFSessionLangCode,b.IETFDatabaseLangCode
    FROM #tempTable b
    LEFT OUTER JOIN User3StringI18N il
        ON il.I18NID = b.I18NID
            AND il.IETFLangCode = b.IETFSessionLangCode
    LEFT OUTER JOIN User3StringI18N id
        ON id.I18NID = b.I18NID
            AND id.IETFLangCode = b.IETFDatabaseLangCode
END

请试试这个

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读