2011-12-14 4 views
2

Итак, я сделал некоторые изменения в хранимой процедуре, которые у нас есть, и теперь требуется 3 часа для запуска (раньше она занимала всего 10 минут). У меня есть временная таблица с именем #tCustomersEmail. В нем есть столбец с именем OrderDate, в котором много нулевых значений. Я хочу заменить эти нулевые значения данными из другой базы данных на другом сервере. Итак, вот что у меня есть:Как повысить производительность этой хранимой процедуры?

создать еще одну временную таблицу:

Create Table #tSouth 
(
CustID char(10), 
InvcDate nchar(10) 
) 

Что я заполнить с этими данными:

INSERT INTO #tSouth(CustID, InvcDate) 
SELECT DISTINCT 
     [CustID], 
     max(InvcDate) as InvcDate 
    FROM D3.SouthW.dbo.uc_InvoiceLine I 
    where EXISTS (SELECT CustomerNumber FROM #tCustomersEmail H WHERE I.CustID = H.CustomerNumber) 
    group BY I.CustID 

Тогда я беру данные из #tSouth и обновления OrderDate в #tCustomersEmail стол, если CustomerNumber соответствует, и OrderDate недействителен:

UPDATE #tCustomersEmail 
SET OrderDate = InvcDate 
FROM #tCustomersEmail 
INNER JOIN #tSouth ON #tCustomersEmail.CustomerNumber = [#tSouth].CustID 
where #tCustomersEmail.OrderDate IS null 

внесения этих изменений вызвали хранимую процедуру принять FOR-EV-ER (пустырь ссылку!)

Так, что я делаю неправильно?

BTW создать индексы моих временных таблиц после того, как я создаю их так:

create clustered index idx_Customers ON #tCustomersEmail(CustomerNumber) 
CREATE clustered index idx_CustSouthW ON #tSouth(CustID) 
+1

Почему все временные таблицы? Если вы злоупотребляете ими, у вас будет узкое место в вашем tempdb. – Oded

+0

Потому что я не могу поставить индексы на реальные таблицы. – broke

+1

Вы создаете временные таблицы ** внутри ** ваш сохраненный proc? Это может привести к перекомпиляции proc - несколько раз. –

ответ

3

Попробуйте пропустить таблицу #tsouth и использовать этот запрос:

UPDATE a 
SET OrderDate = (select max(InvcDate) from D3.SouthW.dbo.uc_InvoiceLine I 
       where a.customernumber = custid) 
FROM #tCustomersEmail a 
WHERE orderdate is null 

Я не думаю, что индекс поможет вы в этом примере

+0

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

2

Distinct не нужен, если у вас есть GROUP BY. Учитывая, что вы переходите через базу данных, мне не нравятся EXISTS. Я бы изменил эту часть, чтобы ограничить количество строк в этой точке. Перейдите на:

INSERT INTO #tSouth(CustID, InvcDate) 
SELECT 
     [CustID], 
     max(InvcDate) as InvcDate 
    FROM D3.SouthW.dbo.uc_InvoiceLine I 
    where I.CustID in 
     (SELECT CustomerNumber 
     FROM #tCustomersEmail H 
     WHERE H.OrderDate IS null) 
    group BY I.CustID 

EDIT: Вы уверены, что вы должны использовать uc_InvoiceLine? Похоже, что должна быть родительская таблица для той, которая имела бы дату и имела бы меньшее количество строк. Кроме того, вы можете пропустить таблицу один временный, выполнив обновление непосредственно:

UPDATE #tCustomersEmail 
SET OrderDate = InvcDate 
FROM #tCustomersEmail 
INNER JOIN (SELECT 
     [CustID], 
     max(InvcDate) as InvcDate 
    FROM D3.SouthW.dbo.uc_InvoiceLine I 
    where I.CustID in 
     (SELECT CustomerNumber 
     FROM #tCustomersEmail H 
     WHERE H.OrderDate IS null) 
    group BY I.CustID) Invoices 
ON #tCustomersEmail.CustomerNumber = Invoices.CustID 
+0

Строка uc_Invoice - это таблица, в которой мне нужна моя информация. Его ненормированная база данных. Я забыл упомянуть об этом. – broke

+0

Причина, по которой я создал #tSouth, заключалась в том, чтобы я мог наложить на нее индекс, так как первичного ключа нет. Ваш способ обновления еще быстрее? – broke

+0

Не знаете, сколько строк вы говорите. Мне нравится, что OrderDate теперь применяется, прежде чем возвращать строки из другой БД - я думаю, что именно это исправит вашу проблему с производительностью. – JBrooks

2

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

В может быть стоит пытаться упростить связанный запрос сервера, чтобы минимизировать шансы всей таблицы быть возвращены по проводам - ​​(как уже упоминалось, вам не нужно как DISTINCT и GROUP BY)

INSERT INTO #tSouth(CustID, InvcDate) 
SELECT [CustID], 
     max(InvcDate) as InvcDate 
    FROM D3.SouthW.dbo.uc_InvoiceLine I 
    group BY I.CustID 

оставив остальную часть запроса без изменений.

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

3

Может быть, использовать таблицу вместо таблицы temp?

declare @temp table 
(
    CustID char(10), 
    InvcDate nchar(10) 
) 

insert into @temp 
... 

Это определенно увеличит производительность!

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