我有一个包含以下现有表格的数据库:
CREATE TABLE [dbo].[sites]
(
[site_id] [uniqueidentifier] NOT NULL,
[description] [nvarchar](80) NOT NULL,
[parent_id] [uniqueidentifier] NULL,
[domain_id] [int] NOT NULL,
CONSTRAINT [PK_sites] PRIMARY KEY NONCLUSTERED ( site_id] ASC
)
ALTER TABLE [dbo].[sites] WITH CHECK
ADD CONSTRAINT [FK_sites_sites]
FOREIGN KEY([parent_id]) REFERENCES [dbo].[sites] ([site_id])
ALTER TABLE [dbo].[sites] CHECK CONSTRAINT [FK_sites_sites]
我添加了另一个看起来像这样的表:
CREATE TABLE [dbo].[site_map]
(
[force_id] [int] NOT NULL,
[source_id] [int] NOT NULL,
[camera_id] [int] NOT NULL,
[site_id] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_site_map] PRIMARY KEY CLUSTERED
([force_id] ASC, [source_id] ASC, [camera_id] ASC)
)
ALTER TABLE [dbo].[site_map] WITH CHECK
ADD CONSTRAINT [FK_site_map_sites]
FOREIGN KEY([site_id]) REFERENCES [dbo].[sites] ([site_id])
ALTER TABLE [dbo].[site_map] CHECK CONSTRAINT [FK_site_map_sites]
现在,当我执行此查询时:
SELECT
m.[site_id], c.[description], s.[site_id] AS ReaderId, s.[domain_id]
FROM
[dbo].[site_map] AS m
LEFT OUTER JOIN
[dbo].[sites] AS c ON m.[site_id] = c.[site_id]
LEFT OUTER JOIN
[dbo].[sites] AS s ON c.[parent_id] = s.[site_id]
WHERE
[force_id] = @forceId
AND [source_id] = @sourceid
AND [camera_id] = @cameraId
我得到一个执行两个嵌套循环的查询计划。但是,当我更改查询时,它的内容如下:
SELECT
m.[site_id], c.[description], s.[site_id] AS ReaderId, s.[domain_d]
FROM
[dbo].[site_map] AS m
INNER JOIN
[dbo].[sites] AS c ON m.[site_id] = c.[site_id]
INNER JOIN
[dbo].[sites] AS s ON c.[parent_id] = s.[site_id]
WHERE
[force_id] = @forceId
AND [source_id] = @sourceid
AND [camera_id] = @cameraId
查询计划执行四个嵌套循环!唯一改变的是连接类型。为什么查询计划如此不同?
答案 0 :(得分:0)
您是否真的注意到性能差异?
我的猜测是INNER JOIN仍然更有效率。看看"执行次数"查询计划中每个嵌套循环操作的数量。我猜测LEFT JOINS有天真的嵌套循环操作,或者至少是一个效率较低的扫描输入,并且INNER JOIN的执行次数较少,可能不是左边的完整笛卡尔循环在x侧右侧,它们可能只在左侧每行执行一次。很难说没有看到查询计划。
我将SET STATISTICS IO打开,刷新您的缓存,看看每次操作得到多少逻辑读取,看看有什么区别。
答案 1 :(得分:0)
(在SQL Server Compact DB上,可能表现不同):
SELECT m.[site_id], c.[description], s.[site_id] AS ReaderId, s.[domain_id]
FROM [site_map] AS m
LEFT OUTER JOIN [sites] AS c ON m.[site_id] = c.[site_id]
LEFT OUTER JOIN [sites] AS s ON c.[parent_id] = s.[site_id]
WHERE [force_id] = 1 AND [source_id] = 1 AND [camera_id] = 1
SELECT m.[site_id], c.[description], s.[site_id] AS ReaderId, s.[domain_id]
FROM [site_map] AS m
INNER JOIN [sites] AS c ON m.[site_id] = c.[site_id]
INNER JOIN [sites] AS s ON c.[parent_id] = s.[site_id]
WHERE [force_id] = 1 AND [source_id] = 1 AND [camera_id] = 1
抱歉,我在第二个执行计划中看不到四个循环。如果您提供执行计划的屏幕截图,那将会很有帮助。