代码之家  ›  专栏  ›  技术社区  ›  Marc Guillot

在FireDAC上使用标量函数的SQL Server查询速度非常慢,而且仅在FireDAC上

  •  0
  • Marc Guillot  · 技术社区  · 5 年前

    我有一个SQL Server查询,在SQL Server Management Studio或TADOQuery上以毫秒为单位运行,但在TFDQuery上运行需要17秒。

    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)
    

    我在一个新的TFDConnection和TFDQuery上运行它们,默认情况下使用它们的所有选项。具有 SET TRANSACTION ISOLATION LEVEL READ COMMITTED 我确保它在与SQL Server Management Studio相同的隔离级别上运行。具有 into #DADES 我强制不返回任何数据(而是将其复制到一个临时表中),这样我就可以避免任何潜在的问题和将数据提取到本地缓冲区的延迟。最后 WITH(RECOMPILE) 我强制SQL Server重新评估查询的执行计划(以防止使用带有过时统计信息的旧计划)。

    此外,我还尝试禁用TFDConnection的ResourceOptions上的所有命令文本处理选项,但没有任何改进。

    这个问题似乎与 dbo.f_pes_linia_comanda() 函数,因为用表达式替换它会使同一查询在毫秒内正确运行。比如:

    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)
    

    所以我的问题是,如果有人知道为什么FireDAC在使用标量函数时运行查询速度较慢?,为什么他们会使用与直接向SQL Server Management Studio上的引擎发送完全相同的查询不同的执行计划?,或者,有没有一种方法可以让TFDQuery使用执行计划,这样我就可以看到它出了什么问题,并尝试解决它?。

    非常感谢。

    0 回复  |  直到 5 年前
    推荐文章