预赛:
我们的应用程序可以从附加的客户端 SQL Server 2005 或 2008 数据库中读取数据,但除了使用临时表外,不会对其进行任何更改。我们可以在他们的服务器上在我们自己的数据库中创建表。
该解决方案必须在 SQL Server 2005 中运行。
架构:
这是模式的简化概念。
组- 定义一组位置的特征
位置- 定义一个地理位置的特征。它链接到组表。
GroupCondition - 链接到一个组。它定义了适用于属于该组的位置子集的度量。
GroupConditionCriteria - 链接到 GroupCondition 表。它为 where 子句中的单个短语命名属性、值、关系运算符和布尔运算符。命名属性是 Location 表的所有字段。有一个序号。GroupConditionCriteria 中的多行必须以正确的顺序串在一起以形成完整的过滤条件。此筛选条件隐式限制为属于与 GroupCondition 关联的组的那些位置。满足过滤条件的位置记录为“包含”,不满足的位置记录为“排除”。
目标:
我们现有的许多查询都从位置表中获取属性。我们想加入一些东西(表、临时表、查询、CTE、openquery、UDF 等),这将为我们提供那些“包含”的位置的 GroupCondition 信息。(一个位置可以包含在多个规则中,但这是一个单独的问题。)
我想要的架构是:
CREATE TABLE #LocationConditions
(
[PolicyID] int NOT NULL,
[LocID] int NOT NULL,
[CONDITIONID] int NOT NULL,
[Satisfies Condition] bit NOT NULL,
[Included] smallint NOT NULL
)
PolicyID标识组,LocID标识Location,CONDITIONID标识GroupCondition,如果过滤器包含位置记录,[满足条件]为1。(包括来自不同的规则表,强制覆盖过滤条件。对于本次讨论并不重要。)
问题大小:
到目前为止,我的最大努力可以创建这样一个表,但速度很慢。对于我正在测试的当前数据库,有 50,000 个位置受到潜在匹配规则 (GroupConditions) 的影响(包括或排除)。执行时间为 4 分钟。如果我们定期刷新并使用永久表,这可能是可行的,但我希望更快。
我尝试了什么:
我使用了一系列 CTE,其中一个是递归的,将过滤条件的几个部分连接成一个大的过滤条件。作为这种情况的一个例子:
(STATECODE = 'TX' AND COUNTY = 'Harris County') OR STATECODE = 'FL'
过滤条件中可以提到一到五个字段,并且可以使用任意数量的括号对它们进行分组。支持的运算符有 lt、le、gt、ge、=、<>、AND 和 OR。
一旦我有了条件,它仍然是一个文本字符串,所以我创建了一个插入语句(必须动态执行):
insert into LocationConditions
SELECT
1896,
390063,
38,
case when (STATECODE = 'TX' AND COUNTY = 'Harris County') OR STATECODE = 'FL' then 1
else 0
end,
1
FROM Location loc
WHERE loc.LocID = 390063
我首先将插入语句添加到它们自己的临时表中,称为#InsertStatements,然后用游标循环它们。我使用 EXEC 执行每个插入。
CREATE TABLE #InsertStatements
(
[Insert Statement] nvarchar(4000) NOT NULL
)
-- Skipping over Lots of complicated CTE's to add to #InsertStatements
DECLARE @InsertCmd nvarchar(4000)
DECLARE InsertCursor CURSOR FAST_FORWARD
FOR
SELECT [Insert Statement]
FROM #InsertStatements
OPEN InsertCursor
FETCH NEXT FROM InsertCursor
INTO @InsertCmd
WHILE @@FETCH_STATUS = 0
BEGIN
--PRINT @InsertCmd
EXEC(@InsertCmd)
FETCH NEXT FROM InsertCursor
INTO @InsertCmd
END
CLOSE InsertCursor
DEALLOCATE InsertCursor
SELECT *
FROM #LocationConditions
ORDER BY PolicyID, LocID
可以想象,执行 50,000 次动态 SQL 插入很慢。我怎样才能加快速度?