Removendo função com cross apply

 Olá pessoal, tudo bem? Hoje gostaria de compartilhar meu primeiro Tuning na nova empresa, ter conseguido realizar essa melhoraria pro cliente foi muito gratificante pra mim e me deixou muito feliz, então decidi compartilhar com vocês.

Antes de começar a explicar vamos montar o ambiente para teste. Irei disponibilizar 2 scripts, um para criar as tabelas que irei utilizar e outro para criar a função do teste.

Obs: Esse script de criação de tabela, foi feito pelo Fabiano Amorim, uma lenda do tuning.

Segue blog dele: https://blogfabiano.com/

Outra observação importante é que aqui não estarei explicando profundamente sobre o operador apply para quem quiser conhecer sobre, leia esse artigo do Marcio Junior um cara que na minha opinião  é um dos melhores em tuning do Brasil.

Segue blog dele com o post: https://vulgomarcio.home.blog/2019/08/05/voce-conhece-o-operador-apply/

Agora vamos ao cenário, para replicar o cenário do cliente peguei duas tabelas famosas do banco  Northwind que o Fabiano criou uma versão BIG, ou seja com muitos dados para explicar o que o cliente estava querendo fazer.

customersbig = dados do cliente

ordersbig = Descrição das vendas

Basicamente precisamos pegar a última venda do cliente por determinada data.

Essa é a query com a função

select 

a.CityID

,a.CompanyName

,a.ContactName

,b.value

,B.orderid

,a.CustomerID

from customersbig a

inner join ordersbig b

on a.customerid= b.customerid

where orderid =  [dbo].menor_venda_por_data(a.customerid,'2021-05-11')


Essa query aqui rodou em 13 segundos:







Observem o número logical reads e cpu

Agora a query com cross apply :





select 

a.CityID

,a.CompanyName

,a.ContactName

,b.value

from  customersbig a

join ordersbig b

on  a.customerid= b.customerid

cross apply (

select  IsNull(Min(orderid),-1) as orderid from  ordersbig b

where  a.customerid= b.customerid

and  orderdate =   '2021-05-11'

)  as d

where d.orderid = b.orderid


Essa query roda em 1 segundo.
Podemos observar que os números de logical reads e cpu são menores em comparação com a função!!
Excelente né? Eu sei que existem outras possibilidades, como por exemplo reescrever a função para inline function e utilizar cross apply ou até mesmo outra reescrita de T-SQL, caso vocês tenham coloquem  nos comentários e vamos debater!!



Segue querys para criação do cenário
download do banco  Northwind

https://docs.microsoft.com/pt-br/dotnet/framework/data/adonet/sql/linq/downloading-sample-databases


script de criação das tabelas bigs do Fabiano e function teste
https://drive.google.com/file/d/18g0K2dzltTW-u5rR3wnJmsYtj9p9R_3w/view?usp=sharing











Comentários

  1. Pessoal o Marcio Junior me mandou essa solução, reparem no order by, essa sintaxe é muito útil e nunca vi sendo utlizada.
    ;WITH CTE
    AS
    (
    SELECT TOP 1 WITH TIES
    b1.Value,
    CustomerID
    FROM
    OrdersBig b1
    WHERE
    OrderDate = '2021-05-11'
    ORDER BY
    ROW_NUMBER() OVER(PARTITION BY b1.CustomerID ORDER BY orderid)
    )
    SELECT
    a.CityID,
    a.CompanyName,
    a.ContactName,
    b.Value
    FROM
    customersbig a
    INNER JOIN CTE B ON a.CustomerID = b.CustomerID

    ResponderExcluir

Postar um comentário

Postagens mais visitadas deste blog

Tuning no Postgres utlizando View Materializada

Como realizei um tuning que caiu o tempo de execução de 8h para 7minutos!

Procedure que cria um script de insert.