1

次の 2 つのクエリがあります。元のクエリは 1 つ目で、2 つ目はわずかな「アップグレード」です。最初の実行には 1 秒近くかかり、2 番目の実行は更新ボタンから指を完全に離す前に終了します。

私の質問: なぜですか?

1 つ目と 2 つ目の唯一の違いは、1 つ目は 合体 を使用して berp.ID_PART_SESSION と比較する値を取得し、2 つ目はユニオンを使用して 2 つの select ステートメントをまとめて同じことを実行することです。

同じ結果を得るために少ない作業を行う必要があるように見えるため、最初のものはより高速である必要があると思います (合体を使用した元の理由)。実行計画の解読がいかに弱いかを考えると、2番目のクエリが最初のクエリよりもはるかに優れている理由を誰か説明してもらえますか?

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

クエリ内のさまざまなテーブルの相対的なサイズとインデックスを理解せずに、決定的な答えを提供することは困難です。1 つの可能性: t_part_session と t_pss_temp の両方が大きい場合、クエリ オプティマイザーは、最初のクエリの内部 SELECT で 2 つの LEFT JOIN を使用して非効率的な処理を行っている可能性があります。

明確にするために編集: はい、両方のクエリに LEFT JOIN がありますが、私の推測では、2 つを一緒にすると (クエリ 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

私はそれが合体の声明だと確信しています。合体は、where句の前に適用されることになると思います。したがって、実際には2つのテーブルの各組み合わせを通過し、where句に一致するテーブルをフィルタリングします。

于 2011-04-07T15:57:36.700 に答える
0

両方のクエリを SSMS の同じバッチに入れ、実行計画を表示できます。これにより、並べて表示できるだけでなく、相対的なコストも表示されます。

IN (UNION) は、2 番目を簡単に並列化できることを意味していると思われます。

于 2011-04-07T14:52:50.627 に答える