SQL查询需要很长时间才能执行

时间:2015-04-17 18:54:43

标签: sql-server

我正在尝试在SQL Server 2008上执行相同查询的两个版本。

版本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

代理费:

我选择的任何东西都不是聚集的

请有人建议我如何改善查询的效果吗?

3 个答案:

答案 0 :(得分: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)

答案 1 :(得分:1)

有一些一般提示

  1. 使用SQL Server Profiler查找成本最高的部分
  2. 在联接列fforder
  3. 上使用索引
  4. CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date)会一次又一次地重复,如果有可能在表中创建一个计算机列并存储该值并在此新列上创建一个索引,并在
  5. 上包含索引选项
  6. 如果无法使用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 :(得分:0)

昂贵的部分是您从外部服务器获取详细数据然后汇总它的地方。你应该总结一下,然后才能把它归还。我不清楚&#34; dtcreated&#34;和&#34; closeoutdate&#34;有关系?

下面我按月汇总数据,然后将其转移到本地服务器。因此,每个订单只有12行而不是一行。如果费用应计入&#34; closeoutdate&#34;这可能不是您想要的。月。但是如果有不同年份的日期,那么您的代码就会出现问题,即它永远不会计入订单或费用。 (需要弄清楚需要什么。)

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