Sql 替换子句中的大WHERE列

Sql 替换子句中的大WHERE列,sql,sql-server,sql-server-2008-r2,Sql,Sql Server,Sql Server 2008 R2,背景 我发现自己陷入了一种有一些非常奇怪的限制的境地。我正在处理的.NET项目有一系列相互层叠的复杂控件。在最底层,正在构造一个SQL查询,其结果将最终填充一个自定义数据网格 该查询的各个部分被传递到一个存储过程中,该存储过程最终构建并执行动态SQL。存储过程的调用如下所示: GetPagedResults @columnList, @fromClause, @whereClause, @pageNumber, @pageSize... WHERE PrimaryKeyColumn IN (l

背景

我发现自己陷入了一种有一些非常奇怪的限制的境地。我正在处理的.NET项目有一系列相互层叠的复杂控件。在最底层,正在构造一个SQL查询,其结果将最终填充一个自定义数据网格

该查询的各个部分被传递到一个存储过程中,该存储过程最终构建并执行动态SQL。存储过程的调用如下所示:

GetPagedResults @columnList, @fromClause, @whereClause, @pageNumber, @pageSize...
WHERE PrimaryKeyColumn IN (list of 1,500 uniqueidentifiers)
问题

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

GetPagedResults @columnList, @fromClause, @whereClause, @pageNumber, @pageSize...
WHERE PrimaryKeyColumn IN (list of 1,500 uniqueidentifiers)
这导致我们的应用程序性能大幅下降。我一直在试图找到纠正这个问题的方法,同时仍然在上面列出的存储过程的范围内工作,因为它是脆弱的,并且在代码库中根深蒂固

我试过的

一,。执行联接,并在SQL中执行所有筛选逻辑

他们用来缩减ID列表的代码长达数百行。用SQL重写可能需要几天的时间,而且我对我们的测试套件没有信心确保我所写的在功能上与当前的解决方案相同

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

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

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]')
)
从MyUdf'…'

我的函数是这样的:

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]')
)
虽然这确保了我创建的是功能对等的东西,但性能非常糟糕。平均而言,它比现有的1000个唯一标识符的解决方案慢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之间执行转换

四,。使用表变量

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

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

所以


我肯定有办法做到这一点,但考虑到我工作的限制,我缺乏想法。在FROM或WHERE子句中有什么可以避免使用大量WHERE[column]in子句的操作吗?

尝试在in子句中使用的表上创建索引,并在DB上重建所有索引。这提高了搜索速度。您不能对FROM子句中的字符串使用SQL split函数并将其连接到juts吗?您考虑过表值参数吗?@KM。我最初不考虑使用SQL拆分函数,因为我读到,与使用SQL的XML特性相比,性能很差。不过,我试过了,效果很好!我会将所有这些值存储在表中,然后直接连接到表中。