Tsql-在分隔列上执行联接-性能和优化问题

Tsql-在分隔列上执行联接-性能和优化问题,sql,performance,tsql,join,Sql,Performance,Tsql,Join,我有以下查询(在返回的列中稍微简化) 例如,这将返回 productA 1 Bob productA 1 Jane productB 2 John,Dave 请注意,客户可以是逗号分隔的列表。我想添加的是“客户位置”列,因此上面的内容变为 productA 1 Bob Ireland productA 1 Jane Wales productB 2 John,Dave Scotland,England 我在下面创建了一个函数,其中fn_sp

我有以下查询(在返回的列中稍微简化)

例如,这将返回

productA  1  Bob
productA  1  Jane
productB  2  John,Dave
请注意,客户可以是逗号分隔的列表。我想添加的是“客户位置”列,因此上面的内容变为

productA  1  Bob        Ireland
productA  1  Jane       Wales
productB  2  John,Dave  Scotland,England
我在下面创建了一个函数,其中fn_split为每个分隔项返回一行

create FUNCTION [dbo].[GetLocations]  (@CustomerNames Varchar(256) )   

RETURNS @TempLocations table (CustomerLocations varchar(256)) AS begin
declare @NameStr varchar(256)  
declare @temp table(singleLoc varchar(256))

insert into @temp
select CustomerLocation.Location from CustomerLocation
INNER JOIN Customers ON Customers.ID = CustomerLocation.ID
INNER JOIN dbo.fn_Split(@CustomerNames,',') split ON split.Item = Customers.Name

SELECT @NameStr = COALESCE(@NameStr + ',', '') + singleLoc 
FROM @temp 

insert into @TempLocations values (@NameStr)
return
end
并将其应用于原始查询,如下所示

select Products.product, Products.ID, Products.Customers, Locations.CustomerLocations
from Products
OUTER APPLY dbo.GetLocations(Products.Customers,',') AS Locations
where Products.orderCompleteDate is null

然而,这是非常缓慢的,对于一个只有2000行的表,查询需要10秒钟(初始查询几乎立即运行)。这表明查询无法优化,正在逐行生成。出于这个原因,我远离标量值函数,并试图坚持使用表值函数。我的逻辑/代码中是否存在明显的错误?

我通常会建议基于未规范化的表创建一个视图,进行规范化,然后将其用作将来任何查询的基础。不幸的是,我无法为您当前的Products表识别PK,但您希望使用
schemabinding
创建此视图,并希望能够将其转换为(PK+客户名称索引)


查询此视图(使用Enterprise Edition或NOEXPAND选项)应该可以提供与标准化表相同的性能。

一个选项是创建第二个表,使产品表标准化,并使其与插入行时调用拆分函数的触发器保持同步

优点是您可以获得标准的性能和简单的SQL查询

缺点是,如果出现任何问题,表可能会失去同步(总是可以安排一个作业,定期从头开始重建新表)


显然,最好的答案是重新设计产品表,但假设您不可能处理拆分函数等。

表中有一个明显的错误,首先存储“分隔”数据。是的,我同意这一点。不幸的是,这不是我能控制的。
select Products.product, Products.ID, Products.Customers, Locations.CustomerLocations
from Products
OUTER APPLY dbo.GetLocations(Products.Customers,',') AS Locations
where Products.orderCompleteDate is null