SQL Server query using an scalar function is very slow on FireDAC and only on FireDAC

426 views Asked by At

I have an SQL Server query that runs in milliseconds on the SQL Server Management Studio or on a TADOQuery, but takes 17 seconds to run on a TFDQuery.

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

if OBJECT_ID('tempdb..#DADES') is not null DROP TABLE #DADES

SELECT 'O' tipus,l.numero as Comanda, o.NumeroOrdre as Ordre, ag.nom as Client,
       c.Referencia, o.estat, max(a.Descripcio) descripcio, ag.provincia, c.ProvinciaEnvio,c.poblacioEnvio,c.codiPostalEnvio,c.adresaEnvio,c.telefonoEnvio,
       c.Transportista, o.ObservacionsTransport, o.DataCarrega, o.DataEntrega,
       case when tipusOrdre=1 then 'PANEL' else case when tipusOrdre=2 then 'TAPAJUNT' else 'ALTRES' end end Tipus2,
       dbo.f_palets_pendents(o.NumeroOrdre) as paletsPendents ,
       dbo.f_palets_assignats(o.NumeroOrdre) as paletsAssignats,
       c.ports,
       sum(dbo.f_pes_linia_comanda(l.numero,L.linia)) pes_lin,
       c.envio
INTO #DADES
FROM OrdresFabricacio o
     LEFT OUTER JOIN LiniesComandesVendes l ON o.NumeroOrdre=l.numeroordre
     LEFT OUTER JOIN CapsaleraComandesVendes c ON c.Numero=l.numero
     LEFT OUTER JOIN CapsaleraAgenda ag ON ag.codi=c.client
     LEFT OUTER JOIN Articles a ON a.codi=l.article
WHERE o.Transport=63163
GROUP BY l.numero,o.NumeroOrdre,ag.nom,c.Referencia, o.estat,ag.provincia,c.ProvinciaEnvio,c.poblacioEnvio,c.codiPostalEnvio,c.adresaEnvio,c.telefonoEnvio,
         c.Transportista, o.ObservacionsTransport, o.DataCarrega, o.DataEntrega,o.tipusOrdre,c.ports,c.envio
OPTION(RECOMPILE)

I run them on a new TFDConnection and TFDQuery with all their options by default. With SET TRANSACTION ISOLATION LEVEL READ COMMITTED I ensure that it runs on the same isolation level that the SQL Server Management Studio. With into #DADES I force that no data is returned (instead it's copied to a temporary table), so I can discard any potential problem and delays fetching the data to local buffers. And finally, with WITH(RECOMPILE) I force SQL Server to re-evaluate the execution plan for the query (to prevent using some old plan with outdated statistics).

Additionally I have also tried disabling all the Command Text Processing options on the ResourceOptions of the TFDConnection, with no improvement.

The problem seems to be related to the dbo.f_pes_linia_comanda() function, because replacing it by an expression makes the same query to run correctly on milliseconds. Something like :

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

if OBJECT_ID('tempdb..#DADES') is not null DROP TABLE #DADES

SELECT 'O' tipus,l.numero as Comanda, o.NumeroOrdre as Ordre, ag.nom as Client,
       c.Referencia, o.estat, max(a.Descripcio) descripcio, ag.provincia, c.ProvinciaEnvio,c.poblacioEnvio,c.codiPostalEnvio,c.adresaEnvio,c.telefonoEnvio,
       c.Transportista, o.ObservacionsTransport, o.DataCarrega, o.DataEntrega,
       case when tipusOrdre=1 then 'PANEL' else case when tipusOrdre=2 then 'TAPAJUNT' else 'ALTRES' end end Tipus2,
       dbo.f_palets_pendents(o.NumeroOrdre) as paletsPendents ,
       dbo.f_palets_assignats(o.NumeroOrdre) as paletsAssignats,
       c.ports,
       sum(l.Quantitat) pes_lin,
       c.envio
INTO #DADES
FROM OrdresFabricacio o
FROM OrdresFabricacio o
     LEFT OUTER JOIN LiniesComandesVendes l ON o.NumeroOrdre=l.numeroordre
     LEFT OUTER JOIN CapsaleraComandesVendes c ON c.Numero=l.numero
     LEFT OUTER JOIN CapsaleraAgenda ag ON ag.codi=c.client
     LEFT OUTER JOIN Articles a ON a.codi=l.article
WHERE o.Transport=63163
GROUP BY l.numero,o.NumeroOrdre,ag.nom,c.Referencia, o.estat,ag.provincia,c.ProvinciaEnvio,c.poblacioEnvio,c.codiPostalEnvio,c.adresaEnvio,c.telefonoEnvio,
         c.Transportista, o.ObservacionsTransport, o.DataCarrega, o.DataEntrega,o.tipusOrdre,c.ports,c.envio
OPTION(RECOMPILE)

So my question is if anyone knows why FireDAC runs queries slower when they have some scalar functions ?, why do they use a different execution plan than when sending directly the exact same query to the engine on SQL Server Management Studio ?, alternatively, is there a way to get the execution plan used for the TFDQuery so I can see what it got wrong and try to work around it ?.

Thank you.

0

There are 0 answers