我有以下两个问题 - 原始是第一个,第二个是我的轻微“升级”。第一个运行需要将近一秒钟,第二个运行完毕才能完全脱离刷新按钮。
我的问题:为什么?
第一个和第二个之间的唯一区别是第一个使用coalesce来获取比较berp.ID_PART_SESSION的值,第二个使用union来将两个select语句放在一起来完成同样的事情。
我仍然认为第一个应该更快(我使用coalesce的原因)因为它似乎应该做更少的工作来得到相同的结果。考虑到我解密执行计划的能力有多弱,有人可以解释为什么第二个查询比第一个查询好得多吗?
declare @animator varchar
SELECT TOP 1 @animator = FULL_NAME
FROM T_BERP berp
INNER JOIN dbo.T_INTERV i ON i.ID_INTERV = berp.ID_INTERV
WHERE berp.VERSION = 1
AND berp.PRINCIPAL = 1
AND berp.DELETED = 0
AND berp.CANCELLED = 0
AND berp.ID_PART_SESSION = (
select coalesce(pss.ID_PART_SESSION, psst.ID_PART_SESSION)
from t_bersp b
LEFT JOIN T_PART_SESSION pss ON b.ID_PART_SESSION = pss.ID_PART_SESSION
LEFT JOIN T_PSS_TEMP psst ON b.ID_PSS_TEMP = psst.ID_PSS_TEMP
where ID_BERSP = 4040)
VS
declare @animator varchar
SELECT TOP 1 @animator = FULL_NAME
FROM dbo.T_BERP berp
INNER JOIN dbo.T_INTERV i ON i.ID_INTERV = berp.ID_INTERV
WHERE berp.VERSION = 1
AND berp.PRINCIPAL = 1
AND berp.DELETED = 0
AND berp.CANCELLED = 0
AND berp.ID_PART_SESSION IN (
select pss.ID_PART_SESSION
from dbo.t_bersp b
LEFT JOIN dbo.T_PART_SESSION pss ON b.ID_PART_SESSION = pss.ID_PART_SESSION
where ID_BERSP = 4040
union
select psst.ID_PART_SESSION
from dbo.t_bersp b
LEFT JOIN dbo.T_PSS_TEMP psst ON b.ID_PSS_TEMP = psst.ID_PSS_TEMP
where ID_BERSP = 4040)
答案 0 :(得分:2)
如果不了解查询中各个表的相对大小和索引,就很难提供明确的答案。一种可能性:如果t_part_session和t_pss_temp都很大,查询优化器可能会在第一个查询的内部SELECT中使用两个LEFT JOIN做一些低效的事情。
编辑澄清:是的,在两个查询中都有LEFT JOIN,但我猜测有两个在一起(查询1)可能会对UNION(查询2)的性能产生负面影响。对不起,如果最初不清楚。
此外,我强烈推荐使用Instant SQL Formatter(与StackOverflow编辑器中的{}图标相结合)等工具,使您的问题中的查询更易于阅读:
DECLARE @animator VARCHAR
SELECT TOP 1 @animator = full_name
FROM t_berp berp
INNER JOIN dbo.t_interv i
ON i.id_interv = berp.id_interv
WHERE berp.version = 1
AND berp.principal = 1
AND berp.deleted = 0
AND berp.cancelled = 0
AND berp.id_part_session = (SELECT
Coalesce(pss.id_part_session, psst.id_part_session)
FROM t_bersp b
LEFT JOIN t_part_session pss
ON b.id_part_session =
pss.id_part_session
LEFT JOIN t_pss_temp psst
ON b.id_pss_temporaire =
psst.id_pss_temporaire
WHERE id_bersp = 4040)
VS
DECLARE @animator VARCHAR
SELECT TOP 1 @animator = full_name
FROM dbo.t_berp berp
INNER JOIN dbo.t_interv i
ON i.id_interv = berp.id_interv
WHERE berp.version = 1
AND berp.principal = 1
AND berp.deleted = 0
AND berp.cancelled = 0
AND berp.id_part_session IN (SELECT pss.id_part_session
FROM dbo.t_bersp b
LEFT JOIN dbo.t_part_session pss
ON b.id_part_session =
pss.id_part_session
WHERE id_bersp = 4040
UNION
SELECT psst.id_part_session
FROM dbo.t_bersp b
LEFT JOIN dbo.t_pss_temp psst
ON b.id_pss_temporaire =
psst.id_pss_temporaire
WHERE id_bersp = 4040)
答案 1 :(得分:0)
您可以将两个查询放入SSMS中的同一批次并显示执行计划 - 这不仅可以让您并排看到它们,还会显示相对成本。
我怀疑IN(UNION)意味着第二个可以很容易地并行化。
答案 2 :(得分:0)
我认为这是合并声明。我相信coalesce最终会在where子句之前应用。所以,它实际上是通过两个表的每个组合,然后过滤那些匹配where子句的那些。