使用 Union All 优化 SQL 查询
Posted
技术标签:
【中文标题】使用 Union All 优化 SQL 查询【英文标题】:Optimising a SQL Query with Union All 【发布时间】:2010-11-09 01:03:26 【问题描述】:我有一个查询,其中包含由 Union All 连接的 4 个选择查询以返回一个结果集,它们是非常复杂的选择查询,但不涉及连接,它们实际上是从 2 个不同的视图中选择的。我只是在考虑优化它,但不确定我应该从哪里开始。 “实际执行计划”说“估计子树成本”是 2.12357,我总是假设如果它超过 1,那么它是一个相当慢的查询?这是一个正确的假设吗?我还检查了整个计划,没有表扫描,只有聚集索引扫描和聚集索引搜索,我再次假设它们可以吗?然而,有很多哈希匹配。无论如何,这个查询会运行很多次,因此我希望它尽可能地优化。希望它有某种意义。
好的,SQL 是这样的
CREATE PROCEDURE [dbo].[CompareFiles] -- Add the parameters for the stored procedure here
@VersionID int,
@SyncRequestID int,
@RegionID int,
@LanguageID int
AS
BEGIN
SELECT 'Delete' AS Action, Type, SUBSTRING(FullPath,2,LEN(FullPath)-1) AS FullPath, FileNameOnServer, FileSize FROM View1
WHERE NOT EXISTS(SELECT 1 FROM View2 where View2.FullPath = View1.FullPath
AND View2.VersionId = @VersionID
AND View2.RegionID = @RegionID
AND View2.LanguageID = @LanguageID
)
AND View1.SyncRequestID = @SyncRequestID
UNION ALL
SELECT 'Add' AS Action, Type, SUBSTRING(FullPath,2,LEN(FullPath)-1) AS FullPath, FileNameOnServer,FileSize FROM View2
WHERE NOT EXISTS(SELECT 1 FROM View1 where View1.FullPath = View2.FullPath AND View1.SyncRequestID = @SyncRequestID)
AND
View2.VersionId = @VersionID
AND View2.RegionID = @RegionID
AND View2.LanguageID = @LanguageID
UNION ALL
SELECT 'Delete' AS Action, Type, SUBSTRING(FullPath,2,LEN(FullPath)-1) AS FullPath, FileNameOnServer, FileSize FROM View2
WHERE EXISTS
(
SELECT 1 FROM View2 fd2
WHERE
View2.FullPath = fd2.FullPath AND fd2.VersionID = @VersionID
AND
View2.FileNameOnServer <> fd2.FileNameOnServer
AND
fd2.RegionID = @RegionID
AND
fd2.LanguageID = @LanguageID
)
AND
View2.VersionId = (SELECT VersionID FROM SyncRequest WHERE SyncRequestID = @SyncRequestID)
AND
View2.RegionID = @RegionID
AND
View2.LanguageID = @LanguageID
UNION ALL
SELECT 'Add' AS Action, Type, SUBSTRING(FullPath,2,LEN(FullPath)-1) AS FullPath, FileNameOnServer, FileSize FROM View2
WHERE EXISTS
(
SELECT 1 FROM View2 fd2
WHERE
View2.FullPath = fd2.FullPath AND fd2.VersionID = (SELECT VersionID FROM SyncRequest WHERE SyncRequestID = @SyncRequestID)
AND
View2.FileNameOnServer <> fd2.FileNameOnServer
AND
fd2.RegionID = @RegionID
AND
fd2.LanguageID = @LanguageID
)
AND
View2.VersionId = @VersionID
AND
View2.RegionID = @RegionID
AND
View2.LanguageID = @LanguageID
END
查看 1 个定义
SELECT DISTINCT fqp.Path + '/' + ISNULL(f.Name, '') + ISNULL(f.Extension, '') AS FullPath, fl.LanguageID, fr.RegionID, f.FileID, dbo.CIT_APD_Versions.ApID, f.FileNameOnServer, dbo.Versions.VersionID, (CASE WHEN FileNameOnServer IS NULL THEN 'Folder' ELSE 'File' END) AS Type, f.FileSize
FROM dbo.FileRegions AS fr
RIGHT OUTER JOIN dbo.Files AS f
INNER JOIN dbo.FilePaths AS fp ON fp.FileID = f.FileID ON fr.FileID = f.FileID
LEFT OUTER JOIN dbo.FileLanguages AS fl ON fl.FileID = f.FileID
LEFT OUTER JOIN dbo.RoleFiles AS fro ON fro.FileID = f.FileID
RIGHT OUTER JOIN dbo.Versions
INNER JOIN dbo.View3 AS fqp ON dbo.VersionID = fqp.VersionID ON fqp.PathID = fp.PathID
查看 2 定义
SELECT '//' + dbo.CIT_APD_SyncRequestFiles.FullPath AS FullPath, NULL AS LanguageID, NULL AS RegionID, NULL AS FileID, NULL AS ApID,
dbo.SyncRequest.VersionID, '' AS FileNameOnServer, '' AS Type, NULL AS FileSize, dbo.SyncRequestFiles.SyncRequestID
FROM dbo.SyncRequestFiles
INNER JOIN dbo.CIT_APD_SyncRequest ON dbo.SyncRequestFiles.SyncRequestID = dbo.SyncRequest.SyncRequestID
查看 3 定义
WITH Parent AS (SELECT PathID, ParentPathID, VersionID, CONVERT(varchar(128), Path) AS Path
FROM dbo.Paths AS ParentPaths
WHERE (ParentPathID = 0)
UNION ALL
SELECT ChildPaths.PathID, ChildPaths.ParentPathID, ChildPaths.VersionID, CONVERT(varchar(128), Parent.Path + '/' + ChildPaths.Path) AS Path
FROM dbo.Paths AS ChildPaths
INNER JOIN Parent ON Parent.PathID = ChildPaths.ParentPathID)
SELECT PathID, ParentPathID, VersionID, Path
FROM Parent
谢谢
【问题讨论】:
没有足够的信息来回答... 大概您的视图包含连接。没有连接的视图没有什么价值(它是一个表!)除非在某些特定情况下,例如隐藏列(授权) 抱歉,你说得对,我会清理SQL并尽快发布 那条评论有点宽泛,米奇。出于性能原因,水平分区数据的视图非常有价值。同样,我一直在视图中对数据进行透视和反透视,以便在 odbc 链接的电子表格中使用。 @Coesy:很好,但是视图定义在哪里? 【参考方案1】:...它们是相当复杂的选择查询,但不涉及连接,它们实际上是从 2 个不同的视图中选择的。
但是视图中有连接吗?这些视图是否有任何共同的表?
如果不查看查询以及视图所代表的查询,那么任何人都无法提供有价值的信息。
【讨论】:
【参考方案2】:“估计子树成本”是 2.12357,我 总是假设它是否超过 1 那么 这是一个很慢的查询
子树成本不能单独用于评估性能。它旨在用于比较执行相同任务的不同查询。因此,假设高成本表示查询性能不佳是不可靠的。
您必须回答“查询在可接受的时间内返回结果吗?”的问题
综上所述,为了放松措辞,较高的子树成本可能支持您的想法,即也许可以改进查询。
没有表扫描,只有 聚集索引扫描
改进查询的更大机会可能是查看为什么会有聚集索引扫描。聚集索引扫描相当于表扫描。正在扫描包括表数据的整个聚集索引。是否必须评估表中的所有行,或者这是否表明存在提高性能的机会?
【讨论】:
【参考方案3】:通过索引调整向导运行查询,这可以告诉您哪些索引可以提供帮助。
确实最好分析和识别sql改进,但是您没有发布sql,所以我们无法帮助您。
【讨论】:
以上是关于使用 Union All 优化 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章