2015-04-17 2 views
1

У меня есть две версии одного и того же запроса, которые я пытаюсь выполнить на SQL Server 2008.SQL-запрос занимает очень много времени для выполнения

Версия 1:

select 
    count(a.ordernumber) as Orders, 
    sum(b.agentfees) as AgentFees, 
    sum(a.revenue) as Revenue, 
    CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) as Date 
from 
    orders a 
join 
    [DC-SQL-V2].FaxFile.dbo.[agent fees] b on a.ordernumber = b.fforder 
where 
    a.closeoutdate >= '2014-01-01' 
    and b.dtcreated >= '2014-01-01' 
    and a.closeoutdate < '2015-01-01' 
    and b.dtcreated < '2015-01-01' 
    and a.processserving = 1 
    and a.branchno = '116' 
group by 
    CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) 
order by 
    CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) 

Версия 1 занимает около 3 часов, чтобы закончить, который, очевидно, безумен. Поэтому я создал версию 2, в которой я попытался отфильтровать таблицы перед их присоединением, но это все еще занимает довольно много времени (2 часа и все еще продолжается).

Версия 2:

select 
    count(a.ordernumber) as Orders, 
    sum(b.agentfees) as AgentFees, 
    sum(a.revenue) as Revenue, 
    CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) as Date 
from 
    (select 
     ordernumber, revenue, closeoutdate, processserving, branchno 
    from 
     ORDERS 
    where 
     closeoutdate >= '2014-01-01' 
     and closeoutdate < '2015-01-01' 
     and branchno = '116' 
     and processserving = 1) a 
join 
    (select 
     agentfees, fforder, dtcreated 
    from 
     [DC-SQL-V2].FaxFile.dbo.[agent fees] 
    where 
     dtcreated >= '2014-01-01' 
     and dtcreated < '2015-01-01') b on a.ordernumber = b.fforder 
group by 
    CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) 
order by 
    CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) 

Вот некоторые дополнительные детали:

select count(*) from [DC-SQL-V2].FaxFile.dbo.[agent fees] 

779531 

select count(*) from ORDERS 

3466648 

Вот кластерные столбцы для обеих таблиц (среди других, которые я не выбирая):

ЗАКАЗЫ:

BranchNo 
Closeoutdate 
ProcessServing 

АГЕНТ ТАРИФЫ:

Ничего я выбирающий не кластерные

ли кто-то пожалуйста, быть в состоянии предложить как я могу улучшить производительность моих запросов?

+1

Какие индексы у вас есть на этих таблицах? –

+3

Я бы рекомендовал просмотреть план выполнения, а также проверить, проиндексированы ли объединенные столбцы. – ManojVenkat

+0

Вы никогда не будете рассчитывать заказы, где dtcreated и closeoutdate в разные годы. – JBrooks

ответ

1

Есть некоторые общие советы

  1. Использование SQL Server Profiler, чтобы найти наиболее затратную часть
  2. использовать индекс присоединиться к колонку fforder
  3. CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) повторяется снова и снова, если это возможно создать столбец компьютера в таблице и сохранить значение и создать индекс в этом новом столбце с включением в индексную опцию на
  4. если 3 невозможно использовать таблицу привода, например, как показано ниже

    select * from 
    (
        select col1,col2,..,CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) from table1) drivedTable 
    join ..... 
    
2

Предполагая [DC-SQL-V2] является удаленным, связанный сервер, я рекомендую принести что данные местные первым.

/* Making broad assumptions here. Substitute correct data types */ 
CREATE TABLE #tmpAgentFees (
    agentfees money, 
    fforder int, 
    dtcreated datetime 
); 

INSERT INTO #tmpAgentFees 
    (agentfees, fforder, dtcreated) 
    SELECT agentfees, fforder, dtcreated 
     FROM [DC-SQL-V2].FaxFile.dbo.[agent fees] 
     WHERE dtcreated >= '2014-01-01' 
      AND dtcreated < '2015-01-01'; 

/* Optionally, add an index to perhaps help performance of the join */ 
CREATE INDEX IX_tmpAgentFees_fforder 
    ON #tmpAgentFees(fforder) 
    INCLUDE (agentfees, dtcreated); 

select count(a.ordernumber) as Orders, sum(b.agentfees) as AgentFees, sum(a.revenue) as Revenue, 
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) as Date 
from orders a 
    join #tmpAgentFees b 
     on a.ordernumber = b.fforder 
where a.closeoutdate >= '2014-01-01' 
    and a.closeoutdate < '2015-01-01' 
    and a.processserving=1 
    and a.branchno='116' 
group by 
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) 
order by 
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) 
+0

жаль, что я должен был упомянуть, это среда PROD, я не могу принести удаленные данные. – Patthebug

+1

@Patthebug Конечно, вы можете. Вы просто помещаете результаты вашего подзапроса из Версии 2 в временную таблицу. –

+0

Спасибо, я попробую. Я также обновил вопрос с информацией об индексе. – Patthebug

0

Дорогая часть, где вы получаете подробные данные с иностранного сервера, а затем суммируя ее. Вы должны их суммировать, а затем только вернуть. Мне непонятно, как связаны «dtcreated» и «closeoutdate»?

Ниже я суммировал данные по месяцам и затем переносил их на локальный сервер. Таким образом, только 12 строк появляются вместо одного за заказ. Это может быть не то, что вы хотите, если плата должна учитываться в месяце «closeoutdate». Но у вашего кода была проблема, когда он никогда не посчитал бы заказ или плату, если бы даты были в разные годы. (Необходимо уточнить, что с этим нужно.)

select 
    a.CloseMonth, 
    a.Orders, 
    b.AgentFees 
    a.Revenue 
    from 

    (select year(closeoutdate) * 100 + month(closeoutdate) as CloseMonth, 
    count(a.ordernumber) as Orders, 
    sum(a.revenue) as Revenue 
    from orders 
     where closeoutdate >= '2014-01-01' 
     and closeoutdate < '2015-01-01' 
     and branchno = '116' 
     and processserving = 1 
     group by year(closeoutdate) * 100 + month(closeoutdate)) as a 

    join 
    (select year(dtcreated) * 100 + month(dtcreated) as FeeMonth, 
     sum(agentfees) AgentFees 
    from [DC-SQL-V2].FaxFile.dbo.[agent fees] 
     where 
      dtcreated >= '2014-01-01' 
      and dtcreated < '2015-01-01' 
      group by year(dtcreated) * 100 + month(dtcreated)) b 
    on a.CloseMonth = b.FeeMonth 
    order by a.CloseMonth 
+0

Спасибо за ваш ответ. Я знаю, что мой код не будет считать некоторые заказы, и я в порядке, если выполнение запроса выполняется быстро. Я попробую. – Patthebug

+0

Выполнение этого запроса довольно быстро, но я хотел бы присоединиться к ORDERNUMBER и FFORDER. – Patthebug

Смежные вопросы