Какая альтернатива для наружного применения? - PullRequest
3 голосов
/ 22 февраля 2012

Недавно я добавил внешний запрос в мой запрос.С тех пор этот запрос занимает вечность.Одна из причин, по которой я знаю, что таблица, с которой она связана, - самая большая таблица в базе данных.

select   
    a.*,
    b.*,
    BTab.*,
    BTTab.*
from 
    tableA a 
    join tableB b ON a.ID = b.UID
    join *****
    left join *******
    ....
    ....
    ....
    outer apply 
        (SELECT TOP 1 * 
        FROM 
            biggestTable bt 
        WHERE 
            bt.id = a.id 
            and a.id <> 100 
        ORDER BY a.datetime desc) BTab
    Outer apply
        (SELECT TOP 1 * 
        FROM 
            biggestTable btt
        WHERE 
            btt.id = a.id 
            AND btt.DateTime <> '1948-01-01 00:00:00.000'
            and btt.value = 0 
        order by btt.datetime desc) BTTab
where 
    ..................
    .................
    ....................
    .................

Есть ли лучшее решение, чем использование внешнего применения?

Ответы [ 2 ]

7 голосов
/ 22 февраля 2012

Вот альтернатива, не могу сказать, лучше 1002 * или нет.Вам может просто потребоваться более качественные индексы на вашем большом столе

WITH BTAB as 
(       SELECT TOP 1 
            * ,
            row_nubmer() over (partition by b.id) rn 

        FROM 
            biggestTable bt 
) ,
BTTab as (SELECT TOP 1 
              * ,
              row_nubmer() over (partition by btt.id order by btt.datetime desc) rn 
        FROM 
            biggestTable btt
        WHERE 
            AND btt.DateTime <> '1948-01-01 00:00:00.000'
            and btt.value = 0 
)

select   
    a.*,
    b.*,
    BTab.*,
    BTTab.*
from 
    tableA a 
    join tableB b ON a.ID = b.UID
    join *****
    left join BTab on ON a.ID = BTab.ID 
           and BTAB.rn = 1
    left join BTTabon ON a.ID = BTTab.ID 
           and BTTab.rn = 1
4 голосов
/ 22 февраля 2012

+ 1 для Конрада, поскольку его ответ может быть всем, что вам нужно, и я повторно использовал часть его синтаксиса.

Проблема с Apply и CTE состоит в том, что они оцениваются для каждой строки в соединении a, b.

Я бы создал две временные таблицы. Чтобы представить максимальные строки и положить на них PK. Преимущество состоит в том, что эти два дорогостоящих запроса выполняются один раз, и соединение выполняется с ПК. Большая выгода от присоединения к ПК. Я ем накладные расходы на #temp, чтобы получить одну оценку и много PK.

   Create table #Btab (int ID PK, ...)
   insert into #Btab
   WITH BTAB as 
   (       SELECT * ,
               row_nubmer() over (partition by b.id) rn 
           FROM 
               biggestTable
           where ID <> 100 
   ) 
   Select * from BTAB
   Where RN = 1 
   order by ID

   Create table #Bttab (int ID PK, ...)
   insert into #Bttab
   WITH BTTAB as 
   (       SELECT * ,
               row_nubmer() over (partition by id order by datetime desc) rn 
           FROM 
               biggestTable
           where DateTime <> '1948-01-01 00:00:00.000' and value = 0
   ) 
   Select * from BTAB
   Where RN = 1 
   order by ID

   select   
       a.*,
       b.*,
       #Btab.*,
       #Bttab.*
   from 
       tableA a 
       join tableB b ON a.ID = b.UID
       join *****
       left join *******
       ....
       ....
       ....
       left outer outer join #Btab 
           on #Btab.ID = a.ID
       left outer outer join #Bttab 
           on #Bttab.ID = a.ID
   where 
       ..................
       .................

P.S. Я исследую TVP над #TEMP для этого. TVP поддерживает PK и имеет меньше накладных расходов, чем #tmp. Но я не сравнивал их один на один в этом типе приложения.

Протестировано TVP через #TEMP и получено улучшение на 1/2 секунды (примерно время, необходимое для создания и удаления временной таблицы).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...