【发布时间】:2019-12-30 12:15:57
【问题描述】:
我意识到,当我使用 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
...
..
.
我想知道是否有一种更有效的方法来检索如此大量的数据,只需一次选择到数据库。
非常感谢一些反馈。
问题中原始方法的响应时间为 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
【问题讨论】:
-
“如您所见,一个查询是按行执行的” 我看不到。在我看来,输出就像是单个查询执行中多行的转储,它只是在每一行输出上重复查询。为什么完全相同的查询的结果(USER_ID 和 PERMISSION)会不同?
-
"问题中原始方法的响应时间为 5726 毫秒" --- 也许您在
principal列上缺少索引,因此查询是进行全表扫描。 -
您是否尝试过自己直接在数据库上运行该查询?
-
是的,我在数据库客户端执行。客户端在 0.098 秒内返回 40 行。显然,该查询总共有 30544 条该 ID 的记录。
-
由于查询返回该ID的30544条记录,并且在DB客户端运行时只显示40行,那么显然DB客户端在40之后停止,您必须滚动才能看到更多,这意味着它没有读取全部30544个结果,计时值比较无意义。再试一次,但这次测量获取所有行的时间。
标签: java database jdbc oracle11g acl