1

我有以下两个查询 - 原来是第一个,第二个是我的轻微“升级”。第一个需要将近一秒钟的时间才能运行,第二个完成后我的手指才能完全离开刷新按钮。

我的问题:为什么?

第一个和第二个之间的唯一区别是第一个使用 coalesce 来获取一个值来比较 berp.ID_PART_SESSION 和第二个使用联合将两个 select 语句放在一起以完成相同的事情。

我仍然认为第一个应该更快(我使用合并的最初原因),因为它似乎应该做更少的工作来获得相同的结果。考虑到我破译执行计划有多弱,有人可以解释为什么第二个查询比第一个好得多吗?

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)

对比

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)
4

3 回答 3

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)

对比

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)  
于 2011-04-07T14:35:17.987 回答
0

您可以在 SSMS 中将两个查询放入同一个批次并显示执行计划——这不仅可以让您并排查看它们,还可以显示相对成本。

我怀疑 IN (UNION) 意味着第二个可以很容易地并行化。

于 2011-04-07T14:52:50.627 回答
0

我打赌这是合并声明。我相信 coalesce 最终会在 where 子句之前应用。所以,它实际上是遍历两个表的每个组合,然后过滤那些与 where 子句匹配的表。

于 2011-04-07T15:57:36.700 回答