Оптимизировать SQL-запрос - PullRequest
0 голосов
/ 13 июля 2009

Я использую следующее, которое выполнить против 1'500'000 строк

Мой SP выглядит следующим образом:

CREATE Procedure USP_12(@AuditMasterID as varchar(10),@TABLE as Varchar(50))
as
BEGIN
Declare @SQLStatement varchar(2000)
Declare @PrefixNo varchar(20)
Declare @PrefixLen varchar(20)
Declare @AfterPrefixLen varchar(20)

DECLARE Cur_Prefix CURSOR
FOR
SELECT PrefixNo,PrefixLen,AfterPrefixLen FROM NoSeriesMaster_Prefix WHERE PrefixType='SMS' order by ID

OPEN Cur_Prefix
FETCH NEXT FROM Cur_Prefix INTO @PrefixNo,@PrefixLen,@AfterPrefixLen
WHILE @@FETCH_STATUS = 0
BEGIN 
SET @SQLStatement = 'update '+@TABLE+' set AuditData.TATCallType=''12'', AuditData.TATCallUnit=''1'' ' +
'from '+@TABLE+' AuditData '+
'inner join AuditMaster am on am.ID=AuditData.AuditMaster_ID '+
'inner join HomeCircleMaster hcm on hcm.Ori_CircleMaster_ID=am.CircleMaster_ID and hcm.Ori_ServiceTypeMaster_ID=1 and hcm.Dest_ServiceTypeMaster_ID=1 '+
'inner join AuditTaggingMaster atm on atm.AuditMaster_ID=am.ID '+
'inner join NoSeriesMaster ns on (ns.CircleMaster_ID=am.CircleMaster_ID or ns.CircleMaster_ID=hcm.Dest_CircleMaster_ID) '+
' and ns.ProviderMaster_ID=am.ProviderMaster_ID '+
' and ns.ServiceTypeMaster_ID=1 '+
'inner join ProviderMaster_CallTypeMaster pm_ctm on pm_ctm.ProviderMaster_ID=am.ProviderMaster_ID and pm_ctm.CallTypeMaster_ID=101 and pm_ctm.CallTypeTagValue=AuditData.CallTypeTag '+
'where AuditData.TATCallType is null and substring(AuditData.CallTo,1,convert(int,'+@PrefixLen+'))='''+ @PrefixNo + ''' and len(AuditData.CallTo)='+convert(varchar(10),convert(int,@PrefixLen)+convert(int,@AfterPrefixLen))+' and '''+@PrefixNo+'''+ns.NoSeries=Left(AuditData.CallTo,len(ns.NoSeries)+convert(int,'+@PrefixLen+')) and AuditData.AuditMaster_ID='+@AuditMasterID+' '
print(@SQLStatement)
exec(@SQLStatement)
FETCH NEXT FROM Cur_Prefix INTO @PrefixNo,@PrefixLen,@AfterPrefixLen
END
CLOSE Cur_Prefix
DEALLOCATE Cur_Prefix
end

Приведенный выше запрос занимает 60 минут для выполнения 1'500'000 строк

Возможна ли оптимизация для этого запроса?

Ответы [ 3 ]

3 голосов
/ 13 июля 2009

Нет. 1 оптимизация - избавьтесь от КУРСОРА! :-) Вы выполняете это против множества разных таблиц ?? Можете ли вы как-нибудь избавиться от переменной @table ??

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

Попробуйте запустить ядро ​​вашего хранимого процесса с этой таблицей 1,5 млн. С жестко закодированным именем таблицы:

update (your table name)
set AuditData.TATCallType='12', AuditData.TATCallUnit='1'
from (your table name) AuditData 
inner join AuditMaster am on am.ID=AuditData.AuditMaster_ID 
 ...... (and so forth)

Сколько времени это занимает само по себе ??

Можете ли вы опубликовать немного больше информации? Табличные структуры, какие показатели доступны?

Марк

PS: я попытался разбить огромный оператор SQL и попытаться избежать CURSOR с помощью Common Table Expression. Однако для этого требуется, чтобы вы жестко закодировали имя @Table в своем утверждении - может ли это сработать для вас ??

Попробуй - сколько времени ты сейчас получаешь?

UPDATE 
    (your table name)
SET 
    AuditData.TATCallType='12', AuditData.TATCallUnit='1'
FROM
    (your table name) AuditData 
INNER JOIN
    AuditMaster am ON am.ID = AuditData.AuditMaster_ID 
INNER JOIN
    HomeCircleMaster hcm ON hcm.Ori_CircleMaster_ID = am.CircleMaster_ID 
          AND hcm.Ori_ServiceTypeMaster_ID = 1 
          AND hcm.Dest_ServiceTypeMaster_ID = 1 
INNER JOIN
    AuditTaggingMaster atm ON atm.AuditMaster_ID = am.ID 
INNER JOIN
    NoSeriesMaster ns on (ns.CircleMaster_ID = am.CircleMaster_ID or ns.CircleMaster_ID = hcm.Dest_CircleMaster_ID) 
      AND ns.ProviderMaster_ID = am.ProviderMaster_ID 
      AND ns.ServiceTypeMaster_ID = 1 
INNER JOIN 
    ProviderMaster_CallTypeMaster pm_ctm ON pm_ctm.ProviderMaster_ID = am.ProviderMaster_ID 
      AND pm_ctm.CallTypeMaster_ID = 101 
      AND pm_ctm.CallTypeTagValue = AuditData.CallTypeTag 
INNER JOIN
    NoSeriesMaster_Prefix PD ON SUBSTRING(AuditData.CallTo, 1, CONVERT(INT, PD.PrefixLen)) = PD.PrefixNo 
      AND LEN(AuditData.CallTo) = CONVERT(VARCHAR(10), CONVERT(INT, PD.PrefixLen) + CONVERT(INT, PD.AfterPrefixLen))
      AND PD.PrefixNo + ns.NoSeries = LEFT(AuditData.CallTo, len(ns.NoSeries) + CONVERT(INT, PD.PrefixLen)) 
WHERE
    AuditData.TATCallType is NULL
    AND AuditData.AuditMaster_ID = @AuditMasterID
    AND PD.PrefixType = 'SMS'

ЕСЛИ это работает, ваши следующие шаги будут проверять, есть ли у вас индексы для

  • все ваши условия JOIN, например,

    ВНУТРЕННЕЕ СОЕДИНЕНИЕ AuditTaggingMaster atm ON atm.AuditMaster_ID = am.ID

    есть ли у вас индексы для "atm.AuditMaster_ID" и "am.ID"?

  • ваши предложения WHERE (например, у вас есть индекс для PD.PrefixType?)

Кроме того, для каждого случая необходимо учитывать, насколько избирательным будет индекс. Например, в вашем предложении WHERE для PD.PrefixType = 'SMS' - это выбирает половину всех записей в таблице "PD" или просто 1-2%? Если индекс является выборочным, то он, скорее всего, будет использоваться - если он находится в столбце «BIT», который может иметь только два значения, и каждое значение выберет около половины таблицы, не беспокойтесь о размещении индекса там, он выиграл ничем не помог.

2 голосов
/ 13 июля 2009

Поскольку вы передаете @table, вам лучше иметь по одному sProc для каждой таблицы, на которой вам нужно это запустить. По крайней мере, у сервера был бы шанс на успех с кэшированным планом.

1 голос
/ 13 июля 2009

Первое, что я хотел бы проверить, это то, что я определил индексы для всех внешних ключей.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...