我可以加快速度吗?

时间:2009-05-12 14:57:05

标签: sql sql-server-2005 performance

我有一系列sps正在运行我们内部开发的数据仓库解决方案。虽然在大多数情况下它运行得很好,但有一个存储过程运行速度非常慢。执行平均需要大约30分钟。我知道瓶颈的确切位置,我只是不知道如何解决它。

基本上,存储过程的作用是创建一系列变量临时表并插入到这些表中。没问题。然后它连接临时表并插入另一个临时表,两次(第二个有点不同)。

这是将表连接并插入临时表的语句,并且是永远需要的部分。任何帮助将不胜感激。

; with Requested as
(
    select distinct 
        PONUMBER as PONumber, 
        min(REQSTDBY) as RequestedBy
    from dw.POP10110
    where REQSTDBY <>''
    group by PONUMBER
)
insert into @tblTableA
(
    PONumber, 
    ReceiptNumber,
    ReceiptLineNumber, 
    VendorID, 
    POType, 
    QuantityShipped, 
    QuantityInvoiced,
    ItemNumber, 
    ItemDescription, 
    UofM, 
    UnitCost, 
    ExtendedCost, 
    SiteID,
    ProjectNumber, 
    AccountID, 
    RequestedBy, 
    GLPostDate, 
    VendorName, 
    CostCategoryID
) 

select 
    a.PONUMBER, 
    a.POPRCTNM, 
    a.RCPTLNNM, 
    a.VENDORID, 
    a.POPTYPE, 
    a.QTYSHPPD, 
    a.QTYINVCD,
    b.ITEMNMBR,
    b.ITEMDESC,
    b.UOFM,
    b.UNITCOST,
    b.EXTDCOST,
    b.LOCNCODE,
    b.ProjNum,
    case i.CostCategoryID 
        when 'MISC' then isnull(i.AccountID,'N/A')

        else 
            case j.CostCategoryID 
                when 'MISC' then 
                    isnull(j.AccountID,'N/A')

                else 
                    isnull(c.PurchaseAccount,'N/A') 
            end
    end as AccountID,
    d.RequestedBy,
    coalesce(e.GLPOSTDT, f.GLPOSTDT, '') as GLPostDate,
    coalesce(e.VENDNAME, f.VENDNAME, '') as VENDNAME,
    case i.CostCategoryID when 'MISC' then i.CostCategoryID else 
        case j.CostCategoryID when 'MISC' then j.CostCategoryID else coalesce(g.CostCategoryID, h.CostCategoryID, '') end
    end as CostCategoryID

from dw.POP10500 a
    inner join dw.POP30310 b
        on a.PONUMBER=b.PONUMBER
            and a.POPRCTNM=b.POPRCTNM
            and a.RCPTLNNM=b.RCPTLNNM
    left outer join @gl00100 c
        on b.INVINDX=c.ActID
    left outer join Requested d
        on b.PONUMBER = d.PONumber
    left outer join dw.POP30300 e
        on b.POPRCTNM=e.POPRCTNM
    left outer join dw.POP10300 f
        on b.POPRCTNM=f.POPRCTNM
    left outer join @pop31310 g
        on b.POPRCTNM=g.ReceiptNumber
    left outer join @pop11310 h
        on b.POPRCTNM=h.ReceiptNumber
    left outer join @pop30390 i
        on a.POPRCTNM=i.ReceiptNumber
    left outer join @pop10390 j
        on a.POPRCTNM=j.ReceiptNumber

据我所知,适当的索引已经到位。

4 个答案:

答案 0 :(得分:2)

临时表/表变量中有多少行?

看起来您正在使用表变量,但如果它们有很多行,请考虑使用临时表(名称以#开头的表)。您可以向这些表添加额外的索引,而表变量只能有一个聚簇索引。

即。转换你的表变量
@ pop31310,@ pop11310,@ pop30390,@ pop10390
进入临时表,并在ReceiptNumber列上为每个表提供一个索引。

答案 1 :(得分:1)

警告:我的大部分经验都是使用Oracle,而不是SQLServer,但我相信答案仍然存在。

通常,您希望最小化连接中的表数,因为优化器必须处理排列,并且往往会感到困惑。使用数据仓库式查询,我会在一个连接中查找不超过三个表,并逐段构建查询。

另一个显而易见的问题是:这些临时表是否已编入索引?如果不是,那么你将不得不对它们进行相对低效的全行连接(如果支持,则为表扫描或散列连接)。

答案 2 :(得分:1)

在变量表(以@开头的那些表)中,可能没有索引。

唯一可以添加到变量表的索引是聚簇索引主键。

这通过OrderID对变量表进行物理排序。

DECLARE @Orders TABLE
(
  OrderID int PRIMARY KEY,
  CustomerID int
  OrderDate datetime
)

这通过CustomerID对@Orders表进行物理排序,并使用OrderID断开联系。它现在适合加入CustomerID。

DECLARE @Orders TABLE
(
  OrderID int,
  CustomerID int
  OrderDate datetime,
  PRIMARY KEY(CustomerID, OrderID)
)

另外 - 请注意,变量表在优化时缺少统计信息。优化器将始终将它们视为具有0行,并且当其他连接类型可能更合适时将使用嵌套循环连接。

答案 3 :(得分:0)

为某些表和索引添加了统计信息,并将时间从25分钟缩短为9分钟。