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
请试试这个 (编辑:宣城站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

