sql-server – SQL Server – 处理嵌套的非确定性视图堆栈中字符
在分析数据库时,我遇到了一个视图,该视图引用了一些非确定性函数,每个连接在此应用程序池中每分钟访问1000-2500次.视图中的简单SELECT产生以下执行计划:
这似乎是一个复杂的计划,一个不到一千行的视图,每隔几个月就会看到一行或两行.但随着以下其他纪念活动,情况会变得更糟: >嵌套视图是非确定性的,因此我们无法对它们编制索引 这对我来说似乎很糟糕,但我只有几年的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表,其中填充了原始基表中干净连接的数据集 现在,我的实际问题: >是否有通过视图处理本地化字符串的最佳实践方法? 解决方法看一下给定的代码,我们可以说,>首先,这不应该是一个视图,但它应该是一个存储过程,因为它不仅仅是从表中读取,而是使用UDF. ,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 请试试这个 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |