2009-07-09 4 views
2

Я хочу обновить TableA со значениями из TableB на ночной основе. Прямо сейчас, я пытаюсь сделать это с помощью SSIS 2005, используя Task Script с SQL в нем. Каждый раз, когда я пытаюсь сделать обновление таким образом, я получаю ошибку тайм-аута.Значения таблицы обновления SSIS из другой таблицы

Есть ли лучший способ сделать это в SSIS?

Текущая информация ниже:

Public Sub Main() 

    Const Component_Name As String = "Updating TableA Data" 
    Const Conn_String As String = "Data Source=DB_A;Initial Catalog=TableA;Integrated Security=SSPI;" 

    Const sql_Emp As String = "Update TableA Set Contract = c.License_No, SEIN = convert(varchar, c.Lic_Exp_Date, 101) " _ 
     & "From Server.DB_B.dbo.TableB c Inner Join TableA b on " _ 
     & "rtrim(ltrim(c.business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14)))) " _ 
     & "Where c.Lic_Exp_Date = (select Max(Lic_Exp_Date) From Server.DB_B.dbo.TableB " _ 
     & "Where rtrim(ltrim(business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14))))) " _ 
     & "and convert(varchar, c.Lic_Exp_Date, 101) <> convert(varchar, b.SEIN, 101)" 

    Dim con As SqlConnection = New SqlConnection(Conn_String) 

    Try 
     Dts.Log("Opening DB Connection: " & con.ConnectionString, 0, Nothing) 

     con.Open() 

     Dim duh As New SqlCommand(sql_Emp, con) 
     duh.ExecuteNonQuery() 

     con.Close() 

     Dts.Log(String.Format(Component_Name), 0, Nothing) 
     Dts.Events.FireInformation(0, Component_Name, String.Format("TableA Data Updating"), "", 0, True) 

     Dts.TaskResult = Dts.Results.Success 

    Catch ex As Exception 
     Dts.Events.FireError(0, Component_Name, ex.Message, "", 0) 
     Dts.Log("Exception detected: " & ex.ToString, 0, Nothing) 
     Dts.TaskResult = Results.Failure 

    End Try 

End Sub 

ответ

3

Давайте очищая, что до немного:

Public Sub Main() 

    Const Component_Name As String = "Updating TableA Data" 
    Const Conn_String As String = "Data Source=DB_A;Initial Catalog=TableA;Integrated Security=SSPI;" 

    Const sql_Emp As String = _ 
      "UPDATE TableA" _ 
      + " SET Contract = c.License_No, SEIN = convert(varchar, c.Lic_Exp_Date, 101)" _ 
     + " FROM Server.DB_B.dbo.TableB c" _ 
     + " INNER JOIN TableA b" _ 
      + " ON rtrim(ltrim(c.business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14))))" _ 
     + " WHERE c.Lic_Exp_Date= (" _ 
      + " SELECT MAX(Lic_Exp_Date)" _ 
      + " FROM Server.DB_B.dbo.TableB" _ 
      + " WHERE rtrim(ltrim(business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14))))" _ 
      + ") AND convert(varchar, c.Lic_Exp_Date, 101) <> convert(varchar, b.SEIN, 101)" 

    Try 
     Using con As New SqlConnection(Conn_String), _ 
       cmds New SqlCommand(sql_Emp, con) 

      Dts.Log("Opening DB Connection: " & con.ConnectionString, 0, Nothing) 

      con.Open() 
      cmd.ExecuteNonQuery() 

      Dts.Log(String.Format(Component_Name), 0, Nothing) 
      Dts.Events.FireInformation(0, Component_Name, String.Format("TableA Data Updating"), "", 0, True) 
      Dts.TaskResult = Dts.Results.Success 
     End Using 

    Catch ex As Exception 
     Dts.Events.FireError(0, Component_Name, ex.Message, "", 0) 
     Dts.Log("Exception detected: " & ex.ToString, 0, Nothing) 
     Dts.TaskResult = Results.Failure 

    End Try 

End Sub 

Хорошо, теперь, когда я могу читать, я могу начать смотреть на то, что может быть нарушена. Вернитесь через несколько минут для редактирования.


Хорошо, теперь давайте посмотрим на этот запрос. Мне не хватает информации о типе данных, поэтому я собираюсь сделать некоторые предположения. Пожалуйста, исправьте все, что не так:

  • b.Account_Key - некоторый тип номера, возможно, int. В противном случае вам не нужно будет преобразовать в VARCHAR
  • Столбцы Lic_Exp_Date действительно имеют тип DateTime

Если те правильно, я думаю, что это будет делать то, что вы хотите, но сделать это в много быстрее:

UPDATE TableA 
    SET Contract = c1.License_No, SEIN = DATEADD(dd,0, DATEDIFF(dd,0, c1.Lic_Exp_Date)) 
FROM TableA b 
INNER JOIN Server.DB_B.dbo.TableB c1 
    ON ISNUMERIC(c1.busines_lic) = 1 AND cast(c1.business_lic AS int) = b.Account_Key 
INNER JOIN 
    (
     SELECT business_lic, MAX(Lic_Exp_Date) AS Lic_Exp_Date 
     FROM Server.DB_B.dbo.TableB 
     GROUP BY business_lic, License_No 
    ) c2 ON c2.business_lic = c1.business_lic AND c1.Lic_Exp_Date=c2.Lic_Exp_Date 
WHERE DATEADD(dd,0, DATEDIFF(dd,0, c1.Lic_Exp_Date)) <> DATEADD(dd,0, DATEDIFF(dd,0, b.SEIN)) 

Вот что изменилось:

  • Включите коррелировала подзапрос в соединение. Присоединение будет намного быстрее, однако оптимизатор запросов, возможно, уже сделал это для вас
  • Устранить необходимость вызова ряда функций для каждой строки - также должно помочь вам лучше совместить индексы.
  • Используйте целое сравнение, а не строки для вашей основной присоединиться к
  • функции даты использования, а не преобразовывать в строки, чтобы удалить временную часть, которая должна быть гораздо быстрее, и в свою очередь, позволит мне:
  • даты Использование сравнений, а чем сравнение строк в вашем соединении
+0

@Joel Coehoorn: WOW! Это полностью ДУМАЕТ, как я это делал !!! Вы - ниндзя SQL! Благодаря! Я также очень ценю ноты внизу. Вы не только задали мне ответ, но и дали мне информацию, чтобы ускорить мои будущие запросы/обновления, обучая меня. Вы действительно хороший человек! – JFV

+0

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

+0

Прошло около 2 минут и 20 секунд с моим исходным кодом. Теперь это занимает 3 секунды. Благодаря! – JFV

2

Лучший способ был бы выполнение задачи SQL. начало

+0

@John Saunders: Вы правы в использовании опции «Выполнять SQL-задачу» вместо «Задача скрипта». Это сделало мой существующий код завершенным без ошибки таймаута. +1 за помощь. – JFV

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