替换大型WHERE列IN子句

时间:2014-02-11 20:40:25

标签: sql sql-server sql-server-2008-r2

背景

我发现自己陷入了一些非常奇怪的限制。我正在研究的.NET项目有一系列相互融合的复杂控件。在最低级别,正在构建SQL查询,其结果将最终填充自定义数据网格。

将此查询的各个部分传递给存储过程,最终构建执行动态SQL。 sproc的调用如下:

GetPagedResults @columnList, @fromClause, @whereClause, @pageNumber, @pageSize...

问题

我的问题源于我的一些前辈写了一些非常糟糕的过滤逻辑。在最激烈的示例中,他们从数据库中检索ID列表,使用一些复杂的过滤逻辑将其删除,然后按如下方式构造WHERE子句:

WHERE PrimaryKeyColumn IN (list of 1,500 uniqueidentifiers)

这导致我们的应用程序性能急剧下降。我一直试图找到解决问题的方法,同时仍然在上面列出的存储过程的范围内工作,因为它在代码库中很脆弱且根深蒂固。

我尝试过什么

1。执行JOIN,并在SQL中执行所有过滤逻辑

他们用来削减ID列表的代码是数百行。使用SQL重写可能需要数天时间,而且我对测试套件没有信心,以确保我编写的内容在功能上与当前解决方案等效。

2。在FROM子句中使用用户定义的函数

为了替换大量的WHERE [column] IN,我尝试创建一个用户定义的函数,该函数将加入ID列表,我将其格式化为XML,因为它是一种表示列表的相对简单的方法。结果使我的查询的FROM子句显示如下:

FROM MyUdf('<root><item id="00000000-0000-0000-0000-000000000000"/>...</root>')

我的功能看起来像这样:

ALTER FUNCTION [dbo].[MyUdf] (@idList XML)
RETURNS TABLE
AS RETURN
(
    SELECT s.* FROM SomeTable s
    JOIN @idList.nodes('/root/item') R (nref) 
        ON s.[PrimaryKeyColumn] = nref.value('@id','[uniqueidentifier]')
)

虽然这确保了我在创造功能相同的东西,但性能却很糟糕。平均而言,它比一组1,000个uniqueidentifier的现有解决方案慢3倍。哎哟。

第3。在输入上进行直接连接

当UDF失败时,我想也许我可以简单地在SELECT语句中将一串uniqueidentifier转换为XML,然后加入它。这会给我一个看起来像这样的FROM子句:

FROM SomeTable s 
JOIN (CONVERT(XML, '<uuids here>')).nodes(/root/item) r(nref)
    ON s.PrimaryKeyColumn = nref.value('@id',[uniqueidentifier])

不幸的是,它似乎不能在关键字JOIN和ON之间执行CONVERT。

4。使用表变量

我觉得这将是理想的路线,我不认为我可以在限制条件下使其工作。我必须调用的存储过程只能让我控制@fromClause和@whereClause。所以我不能在SELECT开始创建表变量之前包含任何SQL语句,并用要过滤的ID填充它。

如果可以在 SELECT语句中创建和填充这样的表,那么它可能会起作用。但是从我所做的阅读中,我认为这不是一种可能性。

因此...

我确信有办法做到这一点,但鉴于我必须努力的限制,我缺乏想法。我可以在FROM或WHERE子句中操作,以避免使用巨大的WHERE [column] IN子句吗?

0 个答案:

没有答案