使用JdbcTemplace.query()时,每行结果都会执行SELECT查询

时间:2019-08-26 09:57:05

标签: java database jdbc oracle11g acl

我意识到,当我执行一个使用JdbcTemplace.query()返回许多记录的简单选择时,数百个选择正在后台执行。 实际上每行一个,由于某些用户在ACL表中的记录数量很多,最终导致性能问题。


private final String PERMISSIONS_QUERY = "SELECT acl.user_id, acl.permission FROM v_user_acls acl WHERE acl.principal = :userId ";
private NamedParameterJdbcTemplate jdbcTemplate;

MapSqlParameterSource params = new MapSqlParameterSource(DAOConstants.USER_ID_KEY, userId);

List<UserPermissionRow> userPermissions = jdbcTemplate.query(PERMISSIONS_QUERY, params,
                new RowMapper<UserPermissionRow>() {
                    @Override
                    public UserPermissionRow mapRow(ResultSet rs, int rowNum) throws SQLException {
                        return new UserPermissionRow(rs.getString(1), rs.getString(2));
                    }
                });

我查看了显示正在执行的查询的P6Spy日志。如您所见,一个查询是按行执行的(我认为效率不高)。


READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10078, PERMISSION =
 READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10079, PERMISSION =
 READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10080, PERMISSION =
 READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10081, PERMISSION =
 READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10082, PERMISSION =
 READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10083, PERMISSION =
 READ
1566811816538|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10084, PERMISSION =
 READ
1566811816538|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10085, PERMISSION =
 READ
1566811816538|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10086, PERMISSION =
 READ
1566811816538|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10087, PERMISSION = READ

...
..
.

我想知道是否有一种更有效的方法,只需选择一个DB就可以检索如此大量的数据。

非常感谢您的反馈。

问题中原始方法的响应时间为5726毫秒。

请参阅以下我尝试的替代方法。 不幸的是,总体时机并没有改善。

选项1(声明)

Statement stmt = dataSource.getConnection().createStatement();
ResultSet rs = stmt.executeQuery(EXPERT_ACCESS_QUERY_2 + userId);
List<UserPermissionTest> list =new ArrayList<UserPermissionTest>();
    // ============= Expert Access Query RAW: 79 ms
while(rs.next()){
    UserPermissionTest e=new UserPermissionTest();
    e.setIdentity(rs.getString(1));
    e.setPermission(rs.getString(2));
    list.add(e);
}
    // ============ 5554 ms

选项2(ResultSetExtractor)

List <UserPermissionTest> userPerms = jdbcTemplate.query(EXPERT_ACCESS_QUERY_2 + userId, 
    new ResultSetExtractor<List<UserPermissionTest>>(){

    @Override
    public List<UserPermissionTest> extractData(ResultSet rs) throws SQLException, DataAccessException {

        List<UserPermissionTest> list =new ArrayList<UserPermissionTest>();
        while(rs.next()){
            UserPermissionTest e=new UserPermissionTest();
            e.setIdentity(rs.getString(1));
            e.setPermission(rs.getString(2));
            list.add(e);
         }
         return list;
    }
});
    //========= 5694 ms

2 个答案:

答案 0 :(得分:1)

也许是因为您在下面的sql脚本中使用单个userId:

private final String PERMISSIONS_QUERY = "SELECT acl.user_id, acl.permission FROM v_user_acls acl WHERE acl.principal = :userId ";

尝试使用IN并在您的where条件下将userID列表用作参数?

我找到了此参考资料是否可以帮助您: https://www.technicalkeeda.com/spring-tutorials/spring-jdbctemplate-in-clause-example

答案 1 :(得分:0)

谢谢。就像Andreas所报告的那样,日志实际上并不是对数据库的调用,而是每次迭代中记录的结果集。 我发现提高性能的唯一解决方案是使用DB View来提高其性能。抱歉造成混乱。