0

预赛:

我们的应用程序可以从附加的客户端 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 插入很慢。我怎样才能加快速度?

4

1 回答 1

2

你必须单独插入每一行?你不能用

insert into LocationConditions 
   SELECT 
      PolicyID, 
      LocID, 
      CONDITIONID, 
      case when (STATECODE = 'TX' AND COUNTY = 'Harris County') OR STATECODE = 'FL' then 1
           else 0 
      end, 
      Included 
   FROM Location loc 

? 你没有展示你是如何创建插入语句的,所以我不知道它是否依赖于每一行。

于 2013-02-19T15:38:37.223 回答