查询vs查询-为什么这个比另一个快



我有以下两个查询-原来是第一个,第二个是我的轻微"升级"。第一个花了将近一秒钟的时间运行,第二个在我的手指完全离开刷新按钮之前就结束了。

我的问题:为什么?

第一个和第二个之间的唯一区别是第一个使用coalesce来获得一个值来比较berp。ID_PART_SESSION with和第二个使用联合将两个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)

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)

如果不了解查询中各种表的相对大小和索引,就很难给出明确的答案。一种可能性是:如果t_part_session和t_pss_temp都很大,查询优化器可能对第一个查询的内部SELECT中的两个LEFT join做了一些效率低下的事情。

编辑澄清:是的,在两个查询中都有LEFT join,但我的猜测是,有两个在一起(查询1)可能会对性能产生不利影响,而不是UNION(查询2)。对不起,如果最初不清楚。

另外,我强烈推荐一个工具,如即时SQL格式化器(结合{}图标在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)  

我打赌这是合并语句。我相信合并最终会在where子句之前应用。因此,它实际上遍历两个表的每个组合,然后对匹配where子句的表进行过滤。

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

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

相关内容

  • 没有找到相关文章

最新更新