查询与查询 - 为什么这个比另一个更快?

发布于 2024-10-30 20:31:09 字数 1537 浏览 4 评论 0原文

我有以下两个查询 - 第一个是原始查询,第二个是我的轻微“升级”。第一个需要将近一秒钟的时间才能运行,而第二个则在我将手指完全从刷新按钮上移开之前完成。

我的问题:为什么?

第一个和第二个之间的唯一区别是,第一个使用合并来获取与 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)

I have the following two queries - the original is the first and the second is my slight "upgrade". The first takes nearly a second to run and the second finishes before I can get my finger completely off of the refresh button.

My question: Why?

The only difference between the first and second is that the first uses coalesce to get a value to compare berp.ID_PART_SESSION with and the second uses a union to put two select statements together to accomplish the same thing.

I still think the first one should be quicker (the original reason why I used coalesce) since it seems like it should be doing less work to get to the same result. Considering how weak I am deciphering execution plans, could someone please explain why the second query is so much better than the first?

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

又怨 2024-11-06 20:31:10

如果不了解查询中各个表的相对大小和索引,就很难提供明确的答案。一种可能性:如果 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)  

It would be difficult to provide a definitive answer without understanding the relative sizes and indices of the various tables in your queries. One possibility: if t_part_session and t_pss_temp are both large, the query optimizer might be doing something inefficient with the two LEFT JOINs in the inner SELECT of your first query.

EDIT to clarify: Yes there are LEFT JOINs in both queries, but my speculation was that having two together (query 1) might adversely affect performance vs the UNION (query 2). Sorry if that wasn't clear initially.

Also, I highly recommend a tool such as the Instant SQL Formatter (combined with the {} icon in StackOverflow's editor) to make the queries in your question easier to read:

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)  
孤独陪着我 2024-11-06 20:31:10

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

I'm betting it's the coalesce statement. I believe that coalesce will end up getting applied before the where clause. So, it's actually going through each combination of the two tables, and THEN filtering on those that match the where clause.

雾里花 2024-11-06 20:31:10

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

我怀疑 IN (UNION) 意味着第二个可以轻松并行化。

You can put both queries into the same batch in SSMS and show execution plan - this will not only let you see them side by side, it will show a relative cost.

I suspect that the IN (UNION) means the second can be easily parallelized.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文