Sql 多次连接两个表的备选方案
我的情况是,我必须多次加入一个表。其中大多数都需要左连接,因为有些值不可用。如何克服多次加入时查询性能差的问题 情景 桌子 [项目]:项目ID Guid,名称VARCHAR(MAX)。Sql 多次连接两个表的备选方案,sql,sql-server,join,sql-server-2008-r2,database-performance,Sql,Sql Server,Join,Sql Server 2008 R2,Database Performance,我的情况是,我必须多次加入一个表。其中大多数都需要左连接,因为有些值不可用。如何克服多次加入时查询性能差的问题 情景 桌子 [项目]:项目ID Guid,名称VARCHAR(MAX)。 [UDF]:EntityId Guid、EntityType字符(1)、UDFCode Guid、UDFName varchar(20) [UDFDetail]:UDFCode Guid,Description VARCHAR(最大值) 关系: [Project].ProjectId-[UDF].EntityId
[UDF]:EntityId Guid、EntityType字符(1)、UDFCode Guid、UDFName varchar(20)
[UDFDetail]:UDFCode Guid,Description VARCHAR(最大值) 关系:
[Project].ProjectId-[UDF].EntityId
[UDFDetail].UDFCode-[UDF].UDFCode UDF表根据UDFName列保存项目的自定义字段。但是,这些字段的值存储在UDFDetail的列描述中。 我有很多用于Project的自定义列,它们存储在UDF表中 例如,要获取项目的两个字段,请执行以下选择:
SELECT
p.Name ProjectName,
ud1.Description Field1,
ud1.UDFCode Field1Id,
ud2.Description Field2,
ud2.UDFCode Field2Id
FROM
Project p
LEFT JOIN UDF u1 ON
u1.EntityId = p.ProjectId AND u1.ItemName='Field1'
LEFT JOIN UDFDetail ud1 ON
ud1.UDFCode = u1.UDFCode
LEFT JOIN UDF u2 ON
u2.EntityId = p.ProjectId AND u2.ItemName='Field2'
LEFT JOIN UDFDetail ud2 ON
ud2.UDFCode = u2.UDFCode
问题
想象一下,上面的select与15个字段连接在一起。在我的查询中,我已经有大约10个字段,并且性能不是很好。运行大约需要20秒。我对这些表有很好的索引,所以看看执行计划,它只进行索引查找,而不进行任何查找。关于连接,它需要左连接,因为该特定项目可能不存在字段1
问题
有没有更有效的方法来检索数据?
在这样的架构中,如何查询一个项目的10个不同字段?这对于注释来说太长了: 您可以选择
pivot
、显式聚合(使用条件函数)或join
s。如果设置了适当的索引,join
s可能是最快的方法
正确的索引应该是UDF(EntityId、ItemName、UdfCode)
您可以通过运行以下查询来测试group by是否更快:
SELECT count(*)
FROM p LEFT JOIN
UDF u1
ON u1.EntityId = p.ProjectId LEFT JOIN
UDFDetail ud1
ON ud1.UDFCode = u1.UDFCode;
如果运行得足够快,那么你可以通过方法考虑<代码>组。
你可以尝试这个非常奇怪的装置(它看起来不漂亮,但它只做一组外部连接)。中间结果是一个非常“宽”和“长”的数据集,然后我们可以通过聚合“压缩”数据集(例如,对于每个ProjectName,每个Field1列将有N个结果、N-1个null和1个非null结果,然后通过简单的最大聚合进行选择)[N是字段数]select ProjectName, max(Field1) as Field1, max(Field1Id) as Field1Id, max(Field2) as Field2, max(Field2Id) as Field2Id
from (
select
p.Name as ProjectName,
case when u.UDFName='Field1' then ud.Description else NULL end as Field1,
case when u.UDFName='Field1' then ud.UDFCode else NULL end as Field1Id,
case when u.UDFName='Field2' then ud.Description else NULL end as Field2,
case when u.UDFName='Field2' then ud.UDFCode else NULL end as Field2Id
from Project p
left join UDF u on p.ProjectId=u.EntityId
left join UDFDetail ud on u.UDFCode=ud.UDFCode
) tmp
group by ProjectName
实际上,可以在不使用内部查询的情况下重写查询,但这不会有太大的区别:),看看Gordon Linoff的建议和您的答案,也可能只需要20秒,但仍然值得一试。将UDF保存为XML是否太晚了?这是一个更好的方法。是的,是的。因为db模式来自第三方。所以我不能修改主结构。我可以在模式中添加我自己的表,但我需要保持默认结构不变。这花了20秒。不仅仅是单独进行左连接。实际上几乎是一样的。可能做
pivot
更快。我怀疑它更好地利用索引进行优化。但是,当您有两个连接时,这可能没有什么区别。我的索引很好。对于每个数据检索操作,该操作都是索引查找。