【发布时间】:2017-10-06 13:22:24
【问题描述】:
我有一个使用此条件连接表的查询:
(Apps.mfrId = Manufacturer.id OR Apps.mfrId IS NULL OR Apps.mfrId = 0)
查询需要 17 秒才能运行,并且使用分析器,查询会导致 5 到 30 条消息(每次运行不同),错误为“错误:1222,严重性:16,状态:18”。
我保留查询完全相同,但我将上述条件更改为:
(Apps.mfrId = Manufacturer.id OR ISNULL(apps.mfrId, 0) = 0)
...现在与这一更改相同的查询在 140 毫秒内运行并且没有锁定错误。
为什么会发生这种情况?
请注意,在对表 Manufacturer 和 Apps 进行测试之前,我已使用 repair_bebuild 选项运行 DBCC CHECKTABLE,并且还重建了两个表上的索引。
另外请注意,没有其他查询同时针对数据库运行。
这是一个有错误的查询的简化版本:
select top 2000 Apps.object_id
from
Manufacturer
INNER JOIN Apps ON (
Apps.mfrId = Manufacturer.Id
OR Apps.mfrId IS NULL
OR Apps.mfrId = 0
)
where
Apps.OBJECT_ID = 6879149
如果我使用“前 1000 名”而不是“前 2000 名”,则查询在 100 多毫秒内完成。
【问题讨论】:
-
你是否展示了每个查询的执行计划?
-
连接条件看起来非常奇怪。这是左连接,内连接,???我对为什么您想要一个连接条件感兴趣,如果apps.mfrid 为空,该连接条件将被覆盖。听起来你只是想要一个完整的加入。最终目标是什么?
-
@scsimon 这是一个内部连接。我正在使用我没有设计的表格。 Apps.mfrId 是 Manufacturer.id 的可为空的外键(没有设置外键约束)。由于某种原因,原始设计允许 NULL 或 0,NULL 或 0 具有相同的含义(即没有设置有效值)。
-
@WEI_DBA 我还没有。我不是 DBA,我只是一个卑微的软件开发人员。我会看看计划,但它可能对我没有帮助。
-
我猜你想在 Apps.mfrId = Manufacturer.id 上离开加入。另外,你的两个例子不一样。我希望 Apps.Field62 不是 Apps.mfrId。当应用程序中没有提供任何值时,您是否打算加入 id 为 0 的行?在这种情况下,您可能需要“ISNULL(apps.mfrId, 0) = Manufacturer.id”。
标签: sql-server sql-server-2008