2009-05-12 4 views
0

Ну, у меня есть серия 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 

Насколько я знаю, соответствующие индексы на месте.

+0

Сколько строк находится в @ pop31310 и подобных таблицах?И сколько строк в запросе? – codeulike

ответ

0

добавил статистику к некоторым таблицам и индексу и сократил время с 25 минут до 9 минут.

2

Сколько строк в ваших временных таблицах/табличных переменных?

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

т.е. преобразовать ваши таблицы значений переменных
@ pop31310, @ pop11310, @ pop30390, @ pop10390
в временные таблицы, и дать каждому из индекса на колонке ReceiptNumber.

+0

max - 137k, самый низкий - 57. Среднее значение составляет около 8k. – DForck42

+0

Да, я считаю, что индексы на временных таблицах помогут. Либо по моему предложению, либо путем добавления кластеризованных индексов к переменным таблицы в соответствии с предложением Дэвида Б. – codeulike

+0

Хорошо, мой друг помогает мне. Я думаю, что мне больше не нужны временные таблицы, и я могу просто присоединиться к фактическим таблицам. причина, по которой они были изначально временными таблицами, заключалась в том, что они были на другом сервере, но теперь я копирую таблицы в одну и ту же базу данных. – DForck42

1

Предостережение: большая часть моего опыта связана с Oracle, а не с SQLServer, но я считаю, что ответ остается.

Как правило, вы хотите минимизировать количество таблиц в соединении, потому что оптимизатор должен будет работать через перестановки и имеет тенденцию путаться. С запросами в стиле хранилища данных я бы поискал не более трех таблиц в одном соединении и строит запросы кусочно.

Другой очевидный вопрос: индексируются ли эти временные таблицы? Если нет, то вам придется сделать относительно неэффективное объединение всех строк на них (либо сканирование таблицы, либо хеш-соединение, если оно поддерживается).

+0

Возможно, но я написал десятки MS-SQL запросов с 20 или 30 соединениями, и оптимизатор едва ли меня подвел – codeulike

1

В таблицах переменных (те, которые начинаются с @), вероятно, нет индексации.

Единственным индексированием, которое можно добавить в таблицу переменных, является первичный ключ кластерного индекса.

Это физически заказывает таблицу переменных по OrderID.

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

Это физически заказывает таблицу @Orders по CustomerID и разрывает связи с помощью OrderID. Теперь он подходит для подключения к CustomerID.

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

Также - имейте в виду, что таблицы переменных не имеют статистики во время оптимизации. Оптимизатор всегда будет рассматривать их как имеющие 0 строк и будет использовать вложенные объединения циклов, когда другие типы соединений могут быть более уместными.

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