Зовнішнє Застосування проти лівого приєднання


37

Я використовую SQL SERVER 2008 R2

Щойно я натрапив на APPLY в SQL і мені сподобалося, як воно вирішує проблеми із запитами для стількох випадків,

У багатьох таблицях я використовував 2 ліві з'єднання, щоб отримати результат, я зміг отримати 1 зовнішнє застосування.

У моїх локальних таблицях БД є невелика кількість даних, і після розгортання код повинен працювати на даних принаймні у 20 разів більше.

Я стурбований тим, що зовнішнє застосування може зайняти більше часу, ніж два ліві умови з'єднання для великого обсягу даних,

Чи може хто-небудь розповісти, як саме застосовується робота і як це вплине на ефективність у дуже великих даних? Якщо можливо, деякі пропорційні співвідношення з розміром кожної таблиці, наприклад, пропорційні n1 ^ 1 або n1 ^ 2 ... де n1 - кількість рядків у таблиці 1.

Ось запит з 2 лівими приєднаннями

select EC.*,DPD.* from Table1 eC left join
  (
   select member_id,parent_gid,child_gid,LOB,group_gid,MAX(table2_sid) mdsid from Table2
   group by member_id,parent_gid,child_gid,LOB,group_gid

  ) DPD2 on DPD2.parent_gid = Ec.parent_gid
        AND DPD2.child_gid = EC.child_gid
        AND DPD2.member_id = EC.member_id
        AND DPD2.LOB = EC.default_lob
        AND DPD2.group_gid = EC.group_gid
  left join
  Table2 dpd on dpd.parent_gid = dpd2.parent_gid 
            and dpd.child_gid = dpd2.child_gid
            and dpd.member_id = dpd2.member_id 
            and dpd.group_gid = dpd2.group_gid 
            and dpd.LOB = dpd2.LOB
            and dpd.table2_sid = dpd2.mdsid

Ось запит із зовнішнім застосуванням

select * from Table1 ec   
OUTER APPLY (
      select top 1 grace_begin_date,retroactive_begin_date,Isretroactive
                    from Table2 DPD 
                    where DPD.parent_gid = Ec.parent_gid
                    AND DPD.child_gid = EC.child_gid
                    AND DPD.member_id = EC.member_id
                    AND DPD.LOB = EC.default_lob
                    AND DPD.group_gid = EC.group_gid
                    order by DPD.table2_sid desc
     ) DPD 

Відповіді:


44

Хто-небудь може сказати, як саме застосовується робота і як це вплине на ефективність у дуже великих даних

APPLYє корельованим з'єднанням (називається LATERAL JOINв деяких продуктах та новіших версіях стандарту SQL). Як і будь-яка логічна конструкція, вона не має прямого впливу на продуктивність. В принципі, ми повинні бути в змозі написати запит, використовуючи будь-який логічно еквівалентний синтаксис, і оптимізатор перетворив би наші дані в точно такий же план фізичного виконання.

Звичайно, це вимагатиме від оптимізатора знати всі можливі перетворення та мати час розглянути кожне. Цей процес може зайняти більше часу, ніж нинішній вік Всесвіту, тому більшість комерційних товарів не застосовують такий підхід. Отже, синтаксис запитів може, і часто має вплив, на остаточну ефективність, хоча складно зробити загальні твердження про те, що краще і чому.

Конкретна форма OUTER APPLY ( SELECT TOP ... ), швидше за все, призведе до приєднання кореляційних вкладених циклів у поточних версіях SQL Server, оскільки оптимізатор не містить логіки для перетворення цього шаблону в еквівалент JOIN. З'єднані між собою вкладені петлі можуть не працювати добре, якщо зовнішній вхід великий, а внутрішній вклад невкладений або потрібні сторінки вже не в пам'яті. Крім того, конкретні елементи вартісної моделі оптимізатора означають, що кореляція вкладених вкладених циклів є меншою ймовірністю, ніж семантично ідентична, JOINщоб створити паралельний план виконання.

Мені вдалося зробити той самий запит з одним лівим приєднанням та row_number ()

Це може бути, а може і не бути кращим у загальному випадку. Вам потрібно буде протестувати обидві альтернативи з репрезентативними даними. LEFT JOINІ , ROW_NUMBERбезумовно , має потенціал , щоб бути більш ефективними, але це залежить від точної форми плану запиту обраної. Основними факторами, які впливають на ефективність такого підходу, є наявність індексу для покриття необхідних стовпців та забезпечення порядку, необхідного PARTITION BYта ORDER BYпунктам. Другий фактор - розмір таблиці. Ефективний та добре проіндексований APPLYможе виконувати ROW_NUMBERз оптимальною індексацією показник, якщо запит стосується порівняно невеликої частини відповідної таблиці. Тестування потрібно.


2

Перший запит може виконуватися паралельно лише одним запитом на sql-сервер. Він отримав увесь запис і дає вихід на основі критеріїв фільтра.

Але у випадку другого, він запускається рядок за рядком, і для кожного рядка таблиця2 буде сканована та додана до результату.

якщо ваш зовнішній запит має менше записів, то другий краще (ЗОВНІШНЕ ЗАЯВКА). Але якщо перший запит може отримати більше даних, то слід скористатися першим.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.