Запрос против запроса - почему этот быстрее, чем другой? - PullRequest
1 голос
/ 07 апреля 2011

У меня есть два следующих запроса: первый - первый, а второй - мое небольшое «обновление».Для запуска первого требуется почти секунда, а для второго - прежде чем я могу полностью убрать палец с кнопки обновления.

Мой вопрос: почему?

Единственная разница между первым и вторымявляется то, что первый использует coalesce, чтобы получить значение для сравнения berp.ID_PART_SESSION, а второй использует объединение, чтобы соединить два оператора 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)

Ответы [ 3 ]

2 голосов
/ 07 апреля 2011

Было бы сложно дать точный ответ без понимания относительных размеров и индексов различных таблиц в ваших запросах.Одна возможность: если t_part_session и t_pss_temp оба велики, оптимизатор запросов может делать что-то неэффективное с двумя левыми соединениями во внутреннем SELECT вашего первого запроса.

EDIT, чтобы уточнить: да, есть левыеПРИСОЕДИНЯЙТЕСЬ к обоим запросам, но мое предположение заключалось в том, что наличие двух вместе (запрос 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)  
0 голосов
/ 07 апреля 2011

Держу пари, это заявление о слиянии.Я полагаю, что слияние в конечном итоге будет применено до предложения where.Таким образом, он фактически просматривает каждую комбинацию двух таблиц и затем фильтрует те из них, которые соответствуют предложению where.

0 голосов
/ 07 апреля 2011

Вы можете поместить оба запроса в один и тот же пакет в SSMS и показать план выполнения - это не только позволит увидеть их рядом, но и отобразит относительную стоимость.

Я подозреваю, что IN (UNION) означает, что второе может быть легко распараллелено.

...