优化MySQL更新查询

时间:2011-01-14 20:40:50

标签: java mysql optimization

这是我的MySQL UPDATE查询,它是用Java编写的程序调用的:

String query = "UPDATE maxday SET DatePressureREL = (SELECT " + 
   "Date FROM ws3600 WHERE PressureREL = (SELECT MAX" +
   "(PressureREL) FROM ws3600 WHERE Date >= '" + Date + 
   "') AND Date >= '" + Date + "' ORDER BY Date DESC LIMIT 1), " +
   "PressureREL = (SELECT PressureREL FROM ws3600 WHERE " + 
   "PressureREL = (SELECT MAX(PressureREL) FROM ws3600 " +
   "WHERE Date >= '" + Date + "') AND Date >= '" + Date + 
   "' ORDER BY Date DESC LIMIT 1), ...";

try {
    s.execute(query);
} 
catch (SQLException e) {
    System.out.println("SQL error");
}
catch(Exception e) {
    e.printStackTrace();
}

首先让我解释一下,它做了什么。我有两个表,第一个是ws3600,它包含列(Date,PressureREL,TemperatureOUT,Dewpoint,...)。然后我有第二个表,名为maxday,它包含DatePressureREL,PressureREL,DateTemperatureOUT,TemperatureOUT等列。现在你可以从一个例子中看到,我更新每一列,问题是,有更快的方法吗?我问这个,因为我两次调用MAX,首先找到该值的日期,然后找到实际值。现在我知道我可以这样写:

SELECT Date, PressureREL FROM ws3600 WHERE PressureREL = 
  (SELECT MAX(PressureREL) FROM ws3600 WHERE Date >= '" + 
  Date + "') AND Date >= '" + Date + "' 
ORDER BY Date DESC LIMIT 1

这样我就可以同时获得最大值和最大值的日期,然后使用这些值更新maxday表中的数据。但是这个解决方案的问题是,我必须执行许多查询,据我所知,与执行一个长的mysql查询相比,由于将每个查询发送到服务器的开销,所以需要更多的时间。

如果没有更好的方法,我应该选择哪种解决方案。第一个,它只需要一个查询但是非常不优化,或者第二个在优化方面更好,但需要更多查询,这可能意味着由于将每个查询发送到服务器的开销而导致性能增益丢失?

4 个答案:

答案 0 :(得分:1)

执行2次查询对我来说并不是一个问题,但是它们应该在事务中(读取和写入),这样您就可以确保更新值没有错误。使用一个查询,您就没有这个问题。

我认为在读取某些数据时丢失的时间与执行写入操作所损失的时间无关。根据定义,写操作不是一件快事,你可能有触发器,你可能会从影响该表的所有请求中清空查询缓存,数据库需要在磁盘上同步你的写操作等。

对您而言,更重要的是保持您的流程简单,可读和逻辑。

答案 1 :(得分:1)

1)我认为问题比SQL优化更深入。您是否认为这可以以不同的方式建模,您不必首先迁移这样的数据(这太多了,而且这通常太顺便了)?也许只是使用FK / cross表将两者连接在一起而不是迁移每个字段?

2)一个查询比使用JDBC不断地在与新语句的连接上来回更好。这是一项非常昂贵的操作(每次)。你总是希望将查询压缩成一个,而不是使用迭代来执行许多语句。

答案 2 :(得分:0)

从内到外工作,看起来所有子查询都做同样的事情。

使用where子句执行Date> ='“+ Date +”'并且Date> ='“+ Date +”'是什么意思?

不进入列名或技术细节,两个表的目的是什么?

String query = @“UPDATE maxday SET DatePressureREL =(SELECT Date FROM ws3600 WHERE PressureREL =(SELECT MAX(PressureREL)FROM ws3600 WHERE Date> = @Date)AND Date> = @Date ORDER BY Date DESC LIMIT 1 ),PressureREL =(SELECT PressureREL FROM ws3600 WHERE PressureREL =(SELECT MAX(PressureREL)FROM ws3600 WHERE Date> = @Date)AND Date> = @Date ORDER BY Date DESC LIMIT 1),...“;

在此之后,理想情况下,如果您使用某种类型的SelectCommand而不是字符串,那么

query.Parameters.Add(new MySqlParameter(“@ Date”,yourdate));

或者,你可以这样做,虽然它可以让你打开sql injection

query = query.replace(“@ Date”,“'”+ Date“'”);

无论哪种方式,它都使查询更加清晰。

答案 3 :(得分:0)

如果您可以在一个选择查询中获取所有值,则可能会有效。使用存储过程接受一个参数(日期):

一个select语句,将值存储在游标中,

一个更新语句,使用游标中的值。

Cursor Example