Чрезмерное время выполнения sql. Как улучшить? - PullRequest
1 голос
/ 21 ноября 2011

У меня следующий SQL-запрос для выполнения в Sql Server MSSM, и для его выполнения требуется более 5 секунд.В таблицах, к которым присоединяется внутреннее соединение, всего несколько десятков тысяч записей.Почему это занимает так много времени?.

Более высокие затраты на запрос: - Сканирование кластерного индекса [MyDB]. [Dbo]. [LinPresup]. [PK_LinPresup_Linea_IdPresupuesto_IdPedido] 78%.- Поиск кластерного индекса [MyDB]. [Dbo]. [Pedidos]. [PK_Pedidos_IdPedido] 19%

Спасибо.

Declare @FILTROPAG bigint 
set @FILTROPAG = 1

Declare @FECHATRABAJO DATETIME
set @FECHATRABAJO = getDate()

Select * from(
SELECT distinct Linpresup.IdCliente, Linpresup.IdPedido, Linpresup.FSE, Linpresup.IdArticulo, 
        Linpresup.Des, ((Linpresup.can*linpresup.mca)-(linpresup.srv*linpresup.mca)) as Pendiente,
        Linpresup.IdAlmacen, linpresup.IdPista, articulos.Tip, linpresup.Linea,
        ROW_NUMBER() OVER(ORDER BY CONVERT(Char(19), Linpresup.FSE, 120) +
             Linpresup.IdPedido + CONVERT(char(2), linpresup.Linea) DESC) as NUM_REG
FROM Linpresup INNER JOIN Pedidos on LinPresup.IdPedido = Pedidos.IdPedido
               INNER JOIN Articulos ON Linpresup.IdArticulo = Articulos.IdArticulo
where  pedidos.Cerrado = 'false' and linpresup.IdPedido <> '' and linpresup.can <> linpresup.srv
        and Linpresup.FecAnulacion is null and Linpresup.Fse <= @FECHATRABAJO 
        and LinPresup.IdCliente not in (Select IdCliente from Clientes where Ctd = '4')
        and Substring(LinPresup.IdPedido, 5, 2) LIKE '11' or Substring(LinPresup.IdPedido, 5, 2) LIKE '10' 
) as TablaTemp
WHERE NUM_REG BETWEEN @FILTROPAG AND 1500   
order by NUM_REG ASC

----------

Это новый запрос с примененными изменениями:

CHECKPOINT;
go
dbcc freeproccache
go
dbcc dropcleanbuffers
go

Declare @FILTROPAG bigint
set @FILTROPAG = 1
Declare @FECHATRABAJO DATETIME
set @FECHATRABAJO = getDate()

SELECT  Linpresup.IdCliente, Linpresup.IdPedido, Linpresup.FSE, Linpresup.IdArticulo, 
        Linpresup.Des, Linpresup.can, linpresup.mca, linpresup.srv,
        Linpresup.IdAlmacen, linpresup.IdPista, linpresup.Linea
into #TEMPREP
FROM Linpresup
where Linpresup.FecAnulacion is null and linpresup.IdPedido <> ''
    and (linpresup.can <> linpresup.srv) and Linpresup.Fse <= @FECHATRABAJO 

Select *, ((can*mca)-(srv*mca)) as Pendiente
From(
    Select tablaTemp.*, ROW_NUMBER() OVER(ORDER BY FSECONVERT + IDPedido + LINCONVERT DESC) as NUM_REG, Articulos.Tip
    From(
            Select #TEMPREP.*, 
                    Substring(#TEMPREP.IdPedido, 5, 2) as NewCol,
                    CONVERT(Char(19), #TEMPREP.FSE, 120) as FSECONVERT, CONVERT(char(2), #TEMPREP.Linea) as LINCONVERT
            from #TEMPREP INNER JOIN Pedidos on #TEMPREP.IdPedido = Pedidos.IdPedido
            where Pedidos.Cerrado = 'false' 
                   and #TEMPREP.IdCliente not in (Select IdCliente from Clientes where Ctd = '4')) as tablaTemp
    inner join Articulos on tablaTemp.IDArticulo = Articulos.IdArticulo
    where (NewCol = '10' or NewCol = '11')) as TablaTemp2
where NUM_REG BETWEEN @FILTROPAG AND 1500   
order by NUM_REG ASC

DROP TABLE #TEMPREP

Общее время выполнения уменьшилось с 5336 до 3978, и время ожидания ответа сервера пришлос 5309 до 2730. Это что-то.

Ответы [ 3 ]

5 голосов
/ 21 ноября 2011

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

and Substring(LinPresup.IdPedido, 5, 2) LIKE '11' 
or Substring(LinPresup.IdPedido, 5, 2) LIKE '10'

функции вокруг имен столбцов в целом приведут к сканированию индекса

2 голосов
/ 21 ноября 2011

Трудно сказать, не видя ваш план выполнения.Тем не менее, в качестве потенциальной опасной точки появляется следующее:

and Substring(LinPresup.IdPedido, 5, 2) LIKE '11' 
or Substring(LinPresup.IdPedido, 5, 2) LIKE '10' 

Я подозреваю, что использование здесь функции substring приведет к тому, что любые потенциально полезные индексы не будут использоваться.Кроме того, почему вы используете LIKE здесь?Я предполагаю, что это, вероятно, оптимизируется, но похоже, что стандартный = будет работать ...

1 голос
/ 21 ноября 2011

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

  • упорядочиваете набор записей дважды (и один раз, когда вы используете конкатенацию и функции),
  • ваше предложение where имеет функции (которые не могут быть sargable) и OR, которые являютсяпочти всегда медленно,
  • , который вы используете не там, где не существует, вероятно, будет быстрее.
  • у вас есть математические вычисления

И вы не упомянули свою индексацию (что может или не может быть полезным) или то, что план выполнения показывает как пятна, которые влияют на производительность больше всего.

Вероятно, я бы начал с извлечения отдельных данных в таблицу CTE или временную таблицу (вы можете индексировать временные таблицы) без вычислений (чтобы при последующих вычислениях он соответствовал наименьшему набору данных).Затем я бы преобразовал подстроки в LinPresup.IdPedido LIKE '1 [0-1]%'.Я преобразую не в не существует.Я бы поставил математику во внешний запрос, так что это делается только для самого маленького набора данных.

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