Java 优化帮助:SQL查询以显示每个国家/地区的最低价格

Java 优化帮助:SQL查询以显示每个国家/地区的最低价格,java,mysql,sql,swing,query-optimization,Java,Mysql,Sql,Swing,Query Optimization,我已经为我的一个客户开发了一个类似代码的投标管理系统。这是一段代码: try { Connection con = Mycon.getConnection(); PreparedStatement ps = con.prepareStatement("TRUNCATE tempcalcplan"); ps.executeUpdate(); ps.clearBatch(); ps = con.prepareStatement("INSERT INTO tem

我已经为我的一个客户开发了一个类似代码的投标管理系统。这是一段代码:

try {
    Connection con = Mycon.getConnection();
    PreparedStatement ps = con.prepareStatement("TRUNCATE tempcalcplan");
    ps.executeUpdate();
    ps.clearBatch();
    ps = con.prepareStatement("INSERT INTO tempcalcplan SELECT v.conid,c.conname, v.rate, v.venid FROM venprices v LEFT JOIN  country c ON c.conid = v.conid WHERE (v.conid, v.rate) IN ( SELECT v.conid, MIN(v.rate) FROM venprices v GROUP BY v.conid) GROUP BY v.conid");
    ps.executeUpdate();
    ps.clearBatch();
    ps = con.prepareStatement("select * from tempcalcplan");

    ResultSet rs = ps.executeQuery();
    jTable1.setModel(DbUtils.resultSetToTableModel(rs));
} catch(Exception e){
    e.printStackTrace();
}
这段代码的设计功能如下:

  • 清空表
    tempclan
    (假设存储了以前的结果)
  • 借助两个不同的表(如下所示)生成所需数据,并将其存储在
    tempclan
    表中
  • 在jTable上显示
    tempclan
    表的结果
  • 以下是
    国家
    tempcalan

  • 国家
    (包含30000条记录)

  • tempclan
    (包含1,80000多条记录)

  • venprices

    +-------+--------------+------+-----+---------+-------+
    | Field | Type         | Null | Key | Default | Extra |
    +-------+--------------+------+-----+---------+-------+
    | conid | int(10)      | NO   | PRI | NULL    |       |
    | rate  | double       | YES  |     | NULL    |       |
    | venid | varchar(50)  | NO   | PRI |         |       |
    +-------+--------------+------+-----+---------+-------+
    
  • 结果需要12-15分钟才能显示在jTable中。
    我想把时间缩短到1-2分钟

    这可能是最耗时的查询:

    INSERT INTO tempcalcplan
        SELECT v.conid, c.conname, v.rate, v.venid
        FROM venprices v LEFT JOIN
             country c
             ON c.conid = v.conid
        WHERE (v.conid, v.rate) IN ( SELECT v.conid, MIN(v.rate) FROM venprices v GROUP BY v.conid) GROUP BY v.conid");
    
    我猜是
    WHERE
    子句引起了问题。尝试将其移动到
    FROM
    子句:

        SELECT v.conid, c.conname, v.rate, v.venid
        FROM venprices v LEFT JOIN
             country c
             ON c.conid = v.conid JOIN
             (SELECT v.conid, MIN(v.rate) as rate
              FROM venprices v
              GROUP BY v.conid
             ) vr
             ON v.conid = vr.conid and v.rate = vr.rate;
    

    我认为您的索引设置得很好,可以进行此查询。

    这可能是最耗时的查询:

    INSERT INTO tempcalcplan
        SELECT v.conid, c.conname, v.rate, v.venid
        FROM venprices v LEFT JOIN
             country c
             ON c.conid = v.conid
        WHERE (v.conid, v.rate) IN ( SELECT v.conid, MIN(v.rate) FROM venprices v GROUP BY v.conid) GROUP BY v.conid");
    
    我猜是
    WHERE
    子句引起了问题。尝试将其移动到
    FROM
    子句:

        SELECT v.conid, c.conname, v.rate, v.venid
        FROM venprices v LEFT JOIN
             country c
             ON c.conid = v.conid JOIN
             (SELECT v.conid, MIN(v.rate) as rate
              FROM venprices v
              GROUP BY v.conid
             ) vr
             ON v.conid = vr.conid and v.rate = vr.rate;
    
    我认为您的索引已经为这个查询设置好了。

    看起来确实比您当前使用的索引有了很大的改进

    SELECT v.conid, c.conname, v.rate, v.venid
    FROM venprices v LEFT JOIN
         country c
         ON c.conid = v.conid JOIN
         (SELECT v.conid, MIN(v.rate) as rate
          FROM venprices v
          GROUP BY v.conid
         ) vr
         ON v.conid = vr.conid and v.rate = vr.rate;
    
    不过,我不确定您是否已经拥有所需的索引。在MySQL中运行以下命令:

    ALTER TABLE `venprices` ADD INDEX `RatesPerConid` (`conid`,`rate`)
    
    创建该索引后,您应该会看到性能显著提高。注
    RatesPerConid
    是索引的名称。你可以把它换成你喜欢的任何东西

    警告:如果一个给定的
    conid
    可能有多个相同最小
    rate
    的实例,您可能需要将
    SELECT
    更改为查询顶部的
    SELECT DISTINCT
    (不在带有GROUP BY的查询中)。

    看起来确实比您当前使用的有很大的改进

    SELECT v.conid, c.conname, v.rate, v.venid
    FROM venprices v LEFT JOIN
         country c
         ON c.conid = v.conid JOIN
         (SELECT v.conid, MIN(v.rate) as rate
          FROM venprices v
          GROUP BY v.conid
         ) vr
         ON v.conid = vr.conid and v.rate = vr.rate;
    
    不过,我不确定您是否已经拥有所需的索引。在MySQL中运行以下命令:

    ALTER TABLE `venprices` ADD INDEX `RatesPerConid` (`conid`,`rate`)
    
    创建该索引后,您应该会看到性能显著提高。注
    RatesPerConid
    是索引的名称。你可以把它换成你喜欢的任何东西


    警告:如果一个给定的
    conid
    可能有多个相同最小
    rate
    的实例,您可能需要将
    SELECT
    更改为查询顶部的
    SELECT DISTINCT
    (不在带有GROUP BY的查询中)。

    我没有设置任何索引。老实说,我实际上不知道如何使用索引。@ArpitPorwal。主键生成索引。谢谢@GordonLinoff,经过一些修改,整个操作在不到2秒钟的时间内完成。但是当我在查询之前将
    insert追加到tempcalan
    中时,它不会被插入到表中。@ArpitPorwal。应该,;这就是
    insert
    的工作原理。唯一不会插入它的方法是,如果
    insert
    生成错误,或者是触发器导致它执行其他操作。我没有设置任何索引。老实说,我实际上不知道如何使用索引。@ArpitPorwal。主键生成索引。谢谢@GordonLinoff,经过一些修改,整个操作在不到2秒钟的时间内完成。但是当我在查询之前将
    insert追加到tempcalan
    中时,它不会被插入到表中。@ArpitPorwal。应该,;这就是
    insert
    的工作原理。它不会被插入的唯一方法是,如果
    插入
    生成了错误,或者触发器导致它执行其他操作。闻起来像--该链接显示了如何有效地执行该操作。闻起来像--该链接显示了如何有效地执行该操作。