【问题标题】:Why my restful api is so slow while execute my SQL query? but it fast when i just run the query为什么在执行我的 SQL 查询时我的 restful api 这么慢?但是当我只运行查询时它很快
【发布时间】:2018-10-09 04:41:18
【问题描述】:

我想要实现的是正常长度(低于 1 分钟)的执行 restful api 时间,我用于前端的技术是使用 Angularjs 和 Java Spring MVC,而后端是 Java Spring MVC Restful API。但它太慢了,这只有一个只返回 2 列的存储过程需要 5 分钟以上。我不知道我做错了什么,因为在我的本地计算机上它工作得很好,但是在服务器上它运行得非常慢,我有其他比这个复杂的查询,它比这个查询执行得更快,这是我的查询看起来像:

    [WEB_SP_Get_Summary]

    ALTER PROCEDURE [dbo].[WEB_SP_Get_Summary]
        @Kd_Plg VARCHAR(50)='KLOP001',
        @Kd_Lokasi VARCHAR(3)='WAT'
    AS
    BEGIN

        SELECT CONVERT(VARCHAR(11),TglJthTempo,106) AS TglJthTempo,
        ISNULL(SUM(PHILIP),0) + ISNULL(SUM(KIM),0) + ISNULL(SUM(HOLIC),0) + ISNULL(SUM(OSRAM),0) + ISNULL(SUM(PANASONIC),0) + ISNULL(SUM([MEGAMEN]),0) AS total_next
        FROM 
        dbo.WEB_F_Dashboard_Get_SisaHutang(@Kd_Plg,@Kd_Lokasi)
        WHERE (TglJthTempo>=GETDATE())
        GROUP BY Kd_Plg,TglJthTempo

    END

Here is my table valued function :


ALTER FUNCTION [dbo].[WEB_F_Dashboard_Get_SisaHutang]
(   
    @Kd_Plg VARCHAR(7),
    @Kd_Lokasi VARCHAR(3)
)
RETURNS @SisaHutang TABLE
(
    Kd_Plg VARCHAR(7),
    TglJthTempo DATETIME,
    PHILIP MONEY,
    KIM MONEY,
    HOLIC MONEY,
    OSRAM MONEY,
    PANASONIC MONEY,
    MEGAMEN MONEY
)
AS
BEGIN
    INSERT INTO @SisaHutang(TglJthTempo,Kd_Plg,PHILIP,KIM,HOLIC,OSRAM,PANASONIC,MEGAMEN)
    SELECT Tgl_JatuhTempo, Kd_Plg, PHILIP, KIM, HOLIC, OSRAM, PANASONIC, MEGAMEN FROM 
        (SELECT a.Divisi,SUM(a.Grandtotal-ISNULL(c.TD,0)) AS sisa_faktur
                ,a.Tgl_JatuhTempo,a.Kd_Plg
        FROM ViewGrandtotal a LEFT JOIN (SELECT No_Faktur, SUM(Total_Distribusi) AS TD
        FROM Trx_DetailDistribusi GROUP BY No_faktur) c ON a.No_Faktur=c.No_faktur 
        WHERE a.GrandTotal - ISNULL(c.TD,0) <> 0
        AND a.Cut_Off = 'A' and a.Kd_Trn='J'
        AND a.Kd_Plg = @Kd_Plg
        AND a.kd_lokasi = @Kd_Lokasi
        GROUP BY a.Divisi, a.Kd_Plg,a.Tgl_JatuhTempo) s
        PIVOT
        (SUM(sisa_faktur)
            FOR Divisi IN (PHILIP,KIM,HOLIC,OSRAM,PANASONIC,MEGAMEN)) AS pvt
RETURN 
END

我的查询有问题吗?

这是我在我的 java 应用程序中请求的方式:

public List<DashboardPiutangAkanDatang> getDashboardPiutangAkanDatang(String Kd_Plg, String Kd_Lokasi) throws DataAccessException {

    Map<String, Object> params = new HashMap<String, Object>();
       params.put("Kd_Plg", Kd_Plg);
       params.put("Kd_Lokasi", Kd_Lokasi);

    ArrayList<DashboardPiutangAkanDatang> dashboard = (ArrayList<DashboardPiutangAkanDatang>) this.namedParameterJdbcTemplate.query
            ("EXEC WEB_SP_Get_Summary :Kd_Plg, :Kd_Lokasi", params, BeanPropertyRowMapper.newInstance(DashboardPiutangAkanDatang.class));  
    return dashboard;

}

【问题讨论】:

  • 这里当然存在延迟问题。 REST 调用访问数据库需要时间,返回数据也需要时间。如果您直接从 SQL Server 本地计算机执行查询或处理,则几乎没有延迟。

标签: java sql-server spring-mvc stored-procedures spring-rest


【解决方案1】:

(评论太长)

代码有异味:

  • 不必要的 TVF 封装,我确信这会导致性能下降;摆脱 TVF,在产品服务器上运行更新的查询并显示实际执行计划
  • GROUP BY, GROUP BY, GROUP BY,.. 非常可疑;
  • LEFT JOIN (SELECT No_Faktur, SUM(Total_Distribusi) AS TD FROM Trx_DetailDistribusi GROUP BY No_faktur) 将导致对 Trx_DetailDistribusi 的整个扫描,而您正在对 leftViewGrandtotal 应用多个过滤器,这意味着 OUTER APPLY 甚至简单的 LEFT JOIN 可以执行得更好
  • ViewGrandtotal 听起来很可疑 - viewtotal 暗示其中正在发生某些事情,并且可能也会受到质疑
  • WHERE a.GrandTotal - ISNULL(c.TD,0) &lt;&gt; 0我不是很喜欢
  • 之后立即将所有列旋转并折叠为单个值?枢轴有什么用?
  • SQL 不是 JAVA,这样的封装和代码“可重用性”正在扼杀它
  • 比较服务器和本地表结构、索引列表
  • 顺便问一下,db 内容是否相等?或者 localhost db 有 10 条记录,而服务器上有数百万条记录?

【讨论】:

    【解决方案2】:

    如果相同的查询给出不同的性能,那么您的执行计划有问题。当您从本地 SSMS 执行过程时,它使用您的 SSMS SET 属性。即 SET ARITH_ABORT ON, ... 这不在 API 请求中。

    请阅读以下文章并在您的程序中进行必要的更改。

    https://www.mssqltips.com/sqlservertip/4318/sql-server-stored-procedure-runs-fast-in-ssms-and-slow-in-application/

    【讨论】:

      猜你喜欢
      • 2021-12-13
      • 2021-08-24
      • 1970-01-01
      • 2011-05-19
      • 2011-03-07
      • 1970-01-01
      • 1970-01-01
      • 2019-09-07
      • 1970-01-01
      相关资源
      最近更新 更多