(J2EE 응용 프로그램에서) PostgreSQL 데이터베이스와 JDBC 드라이버에서 이상한 동작이 발생합니다. 그들 각자는 주어진 날짜에 emited 된 메시지가 포함J2EE - PostgreSQL - JDBC - 느린 쿼리
SHIP_MESSAGE(id, datetime, latitude, longitude)
SUBMARINE_MESSAGE(id, datetime, latitude, longitude, immersion)
:
이의 내가 두 개의 테이블이 있다고 가정 해 보자, 간단하게합니다. 이제는 웹 사이트에서 이러한 정보를 재생해야합니다.나는 AJAX를 사용하여 300-500ms마다 정보를 요청하고 있습니다. 요청은 다음과 같습니다. SHIP_MESSAGE에서 id, datetime, latitude, longitude를 선택하십시오. 여기서 date> = '2013-02-11 18:00:00'order by date limit 1;
한 번 실행하면 (첫 번째 테이블에서 메시지를 가져 오기 위해) 약 150ms가 걸립니다. 그러나 두 번 (두 테이블에서 메시지를 가져 오기 위해) 두 번 실행하면 각 쿼리에 800 ~ 2000ms가 걸립니다!
MessageDAO dao = new MessageDAO(); // Data access object, used to execute my query
Date d1 = new Date();
ShipMessage message = dao.getShipMessageAtDate(date);
Date d2 = new Date();
System.out.println(d2.getTime() - d1.getTime()); // Around 150 ms
을 그리고 이것은하지 않습니다 :
그래서이 작품을 잘 내 연결을 얻기 위해 싱글 톤 패턴을 사용하고
MessageDAO dao = new MessageDAO();
Date d1 = new Date();
NavigationMessage message = dao.getShipMessageAtDate(date);
Date d2 = new Date();
SubmarineMessage m2 = dao.getSubmarinMessageAtDate(date);
Date d3 = new Date();
System.out.println(d2.getTime() - d1.getTime()); // Between 800 and 2000 ms
System.out.println(d3.getTime() - d2.getTime()); // Between 800 and 2000 ms
. 두 개의 Connection 객체를 만들면 너무 잘 작동합니다 (~ 150 ms). 너무 많은 클라이언트가있을 때 충분한 연결을 열 수 없기 때문에 그렇게하지 않으려 고합니다.
아이디어가 있으십니까?
두 메시지의 데이터를 포함하는 하나의 요청 만 사용하려고 시도했지만 너무 길었습니다 (1-3 초). 이는 터미널에서 직접 실행하면 빠르기 때문에 이상합니다. .
감사합니다.
편집 : 여기
가 MessageDAO에 대한 코드입니다 : 여기
public class MessageDAO extends DAO {
public MessageDAO() { super(); }
public MessageDAO(Connection connection) { super(connection); }
public NavSensorsMessage getShipMessageDate(Date date) throws SQLException {
String sql = "select * from BOAT_MESSAGE where date >= ? order by date limit 1;";
PreparedStatement ps = _connection.prepareStatement(sql);
ps.setTimestamp(1, new java.sql.Timestamp(date.getTime()));
ResultSet result = ps.executeQuery();
result.next();
Date datetime = result.getDate("datetime");
float latitude = result.getFloat("latitude");
float longitude = result.getFloat("longitude");
return new ShipMessage(datetime, latitude, longitude);
}
}
는 클래스 DAO이다 :
public abstract class DAO {
// -------------------------------------------------------------------------
protected Connection _connection;
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// Constructors :
public DAO() { _connection = StaticPostgreSQLConnection.getInstance(); }
public DAO(Connection connection) { _connection = connection; }
// -------------------------------------------------------------------------
}
을 그리고 여기에 StaticPostgreSQLConnection입니다 :
public class StaticPostgreSQLConnection {
// -------------------------------------------------------------------------
private static final String _driverName = "org.postgresql.Driver";
private static final String _url = "jdbc:postgresql://localhost:5432/telesciences";
private static final String _user = "mylogin";
private static final String _password = "mypassword";
private static Connection _connection;
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
public static Connection getInstance() {
if (_connection == null) {
try {
Class.forName(_driverName);
_connection = DriverManager.getConnection(_url, _user, _password);
}
catch (ClassNotFoundException | SQLException e) { e.printStackTrace(System.err); }
}
return _connection;
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
public static void close() {
try {
_connection.close();
_connection = null;
}
catch (SQLException e) { e.printStackTrace(System.err); }
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
public static void begin() throws SQLException { getInstance().createStatement().execute("BEGIN;"); }
public static void commit() throws SQLException { getInstance().createStatement().execute("COMMIT;"); }
public static void rollback() throws SQLException { getInstance().createStatement().execute("ROLLBACK;"); }
// -------------------------------------------------------------------------
}
편집 2 :
이2014-02-12 11:02:02 CET LOG: durée : 0.122 ms, analyse <unnamed> : select * from NAVIGATION_MESSAGE where date >= $1 order by date limit 1
2014-02-12 11:02:02 CET LOG: durée : 0.143 ms, lien <unnamed> : select * from NAVIGATION_MESSAGE where date >= $1 order by date limit 1
2014-02-12 11:02:02 CET DÉTAIL: paramètres : $1 = '2011-07-02 01:08:05.16'
2014-02-12 11:02:02 CET LOG: exécute <unnamed>: select * from NAVIGATION_MESSAGE where date >= $1 order by date limit 1
2014-02-12 11:02:02 CET DÉTAIL: paramètres : $1 = '2011-07-02 01:08:05.16'
2014-02-12 11:02:02 CET LOG: durée : 157.295 ms
2014-02-12 11:02:02 CET LOG: durée : 0.114 ms, analyse <unnamed> : select * from NAVSENSORS_MESSAGE where date >= $1 order by date limit 1
2014-02-12 11:02:02 CET LOG: durée : 0.161 ms, lien <unnamed> : select * from NAVSENSORS_MESSAGE where date >= $1 order by date limit 1
2014-02-12 11:02:02 CET DÉTAIL: paramètres : $1 = '2011-07-02 01:08:04.88'
2014-02-12 11:02:02 CET LOG: exécute <unnamed>: select * from NAVSENSORS_MESSAGE where date >= $1 order by date limit 1
2014-02-12 11:02:02 CET DÉTAIL: paramètres : $1 = '2011-07-02 01:08:04.88'
2014-02-12 11:02:02 CET LOG: durée : 157.598 ms
모든 요청은 150 밀리 초 소요, 그래서 문제가 저절로 POSTGRES되지 않은 : 여기
은 포스트 그레스의 조각 로그입니다. 내 연결을 찾는 방식에서 오는 것 같아.
MessageDao의 구현 방법 특히 연결을 가져 오는 방법을 보여줄 수 있습니까? –
상세한 PostgreSQL 쿼리 로깅을 가능하게합니다 - 적어도'log_statement = 'all''과'log_min_duration_statement = 0'. 그런 다음 PostgreSQL이 PostgreSQL 로그에서 명령문이 실행되는 데 걸린 시간을보고합니다. 이렇게하면 지연이 어디에서 발생하는지 파악하는 데 도움이됩니다. 또한'auto_explain'을 활성화하고 JDBC에서 실행할 때 생성 된 계획과 수동으로 실행할 때 생성 된 계획을 비교해보십시오. –
기본 사항을 포함하는 것을 잊었습니다. 정확한 * PgJDBC 버전과 정확한 * PostgreSQL 버전 ('select version()')을 보여주십시오. –