关于mybatis和mysql的性能优化问题
1、尽量不使用多表查询,使用resultMap和延迟加载进行单表查询提高性能
a、延迟加载和懒加载配置,在mybatis的setting标签中
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 按需加载 -->
<setting name="aggressiveLazyLoading" value="true"/>
2、尽量使用主键字段查询,可以显著的提高查询性能
3、尽量使用索引字段查询,理由同上
4、尽量不使用模糊查询,如果使用,请按照
select * from shiro_user where username LIKE ‘S%’
select * from shiro_user where username LIKE '%S'
词首模糊会导致索引失效,进行全表查询
explain语法的使用和详解
explain select * from shiro_user where username LIKE ‘S%’
id:指操作的顺序,从小到大优先度递增,id相同时由上往下执行
selet_type:查询中若包含任何复杂的子部分,最外层查询则被标记
SIMPLE:简单查询,查询中不包含子查询和UNION查询
PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记
SUBQUERY:在SELECT或WHERE列表中包含了子查询,该子查询被标记
DERIVED:在FROM列表中包含的子查询被标记
UNION :若第二个SELECT出现在UNION之后,则被标记
UNION RESULT :从UNION表获取结果的SELECT被标记
type :查找行所需要的方式,性能从低到高
ALL, index, range, ref, eq_ref, const, system, NULL
possible_keys :
指出Mysql能使用哪个索引在表中找到记录,查询涉及记录的字段上若存在索引,则该索引列被抛出,但不是被查询使用
key :
显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL
key_len :
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)
ref :
表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
rows :
表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数
package com.shaw.shiro.pojo;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class User {
private Integer userid;
private String username;
private String password;
//一对多,一个用户对应多个角色
private Set<String> roles;
//一对多,一个用户对应多个权限
private Set<String> permissions;
public Integer getUserid() {
return userid;
}
public void setuserId(Integer userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public Set<String> getPermissions() {
return permissions;
}
public void setPermissions(Set<String> permissions) {
this.permissions = permissions;
}
@Override
public String toString() {
return "User [userid=" + userid + ", username=" + username + ", password=" + password + ", roles=" + roles
+ ", permissions=" + permissions + "]";
}
}
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shaw.shiro.mapper.UserMapper">
<resultMap type="user" id="UserWithRole">
<id column="user_id" javaType="Integer" property="userId"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<!--
这里通过resultMap的懒加载进行一对多查询
效率大大高于连表查询,将查询出来的id字段
作为查询子表的条件进行映射
-->
<collection property="roles" ofType="String" column="user_id" select="SelectRoleByUserId">
</collection>
<collection property="permissions" ofType="String" column="user_id" select="SelectPermissionByUserId"></collection>
</resultMap>
<sql id="Select_where_Cause">
<where>
<choose>
<when test="username!=null">
AND USERNAME LIKE '${username}'
</when>
<when test="password!=null">
AND PASSWORD=#{password}
</when>
</choose>
</where>
</sql>
<sql id="Base_Colum">
USER_ID,USERNAME,PASSWORD
</sql>
<select id="getUser" parameterType="user" resultType="user">
SELECT
<include refid="Base_Colum" />
FROM shiro_user
<include refid="Select_where_Cause" />
</select>
<!-- 查询用户所有信息 -->
<select id="SelectUser" resultMap="UserWithRole">
select
<include refid="Base_Colum"></include>
from shiro_user
<include refid="Select_where_Cause" />
</select>
<!-- 延迟加载查找用户角色 -->
<select id="SelectRoleByUserId" parameterType="Integer" resultType="String">
select role_name from shiro_roles where user_id = #{userId}
</select>
<!-- 延迟加载查找用户权限 -->
<select id="SelectPermissionByUserId" parameterType="Integer" resultType="String">
select permission_name from shiro_permissions where user_id = #{userId}
</select>
</mapper>