问题描述
项目中一个复杂的接口耗时过高,查询的表数据量大,该接口使用了PageHelper进行查询结果进行分页,且该查询sql进行了 联表查询 。通过查看日志,将sql提出,发现是PageHelper组件在进行count计数的时候慢,而这个接口查询因为是分页且走了索引,反而并不慢。
PageHelper.startPage(searchRecordPosition.getPage(), searchRecordPosition.getSize());
List<positionRecordVO> result = positionRecordMapper.getRecordPositionList(searchRecordPosition);
这个是写的sql
<select id="getRecordPositionList" resultType="com.hengtiansoft.hzrc.dal.vo.positionRecordVO">
SELECT p.id AS positionId,p.NAME AS positionName,p.education_id AS
educationId,p.working_years_id AS workYearsId,p.recruit_number AS recruitNumber,
p.high_tech as highTech,p.urgently_hired as urgentlyHired,r.id as recruitmentId,c.id as companyId,
r.way as positionSource,r.name as recruitmentName,r.status as status,c.name as companyName,
c.credit_code as creditCode,p.create_ts as releaseTs,
p.tag_id AS tagId,p.s_region_id AS sRegionId,p.property as property,p.salary_lower as salaryLower,
p.salary_max as salaryMax,p.contact as contact,p.contact_number as contactNumber,p.update_by as updateBy,r.id as
recruitmentId
FROM position_record p
LEFT JOIN recruitment r ON p.recruitment_id = r.id
LEFT JOIN company c ON p.company_id = c.id
<where>
<if test="null != searchPosition.educationId and searchPosition.educationId != ''">
AND p.education_id = #{
searchPosition.educationId}
</if>
<if test="searchPosition.companyId != null and searchPosition.companyId != ''">
and p.company_id = #{
searchPosition.companyId}
</if>
<if test="searchPosition.positionName != null and searchPosition.positionName != ''">
and p.name LIKE CONCAT('%',#{
searchPosition.positionName},'%')
</if>
<if test="searchPosition.companyName != null and searchPosition.companyName != ''">
and c.name LIKE CONCAT('%',#{
searchPosition.companyName},'%')
</if>
<if test="searchPosition.startTime != null and searchPosition.endTime != null">
and p.release_ts<![CDATA[>=]]> #{
searchPosition.startTime}
and p.release_ts <![CDATA[<=]]> #{
searchPosition.endTime}
and p.status != '1'
</if>
<if test="searchPosition.createStartTs !=null ">
and p.create_ts <![CDATA[>=]]> #{
searchPosition.createStartTs}
</if>
<if test="searchPosition.createEndTs !=null ">
and p.create_ts <![CDATA[<=]]> #{
searchPosition.createEndTs}
</if>
<if test="searchPosition.property !=null and searchPosition.property != ''">
and p.property = #{
searchPosition.property}
</if>
<if test="searchPosition.salaryMax !=null and searchPosition.salaryMax != ''">
and p.salary_max <![CDATA[<=]]> #{
searchPosition.salaryMax}
</if>
<if test="searchPosition.salaryLower !=null and searchPosition.salaryLower != ''">
and p.salary_lower <![CDATA[>=]]> #{
searchPosition.salaryLower}
</if>
<if test="searchPosition.workingYearsId !=null and searchPosition.workingYearsId != ''">
and p.working_years_id = #{
searchPosition.workingYearsId}
</if>
<if test="searchPosition.sRegionId !=null and searchPosition.sRegionId != ''">
and p.s_region_id = #{
searchPosition.sRegionId}
</if>
<if test="searchPosition.urgentlyHired !=null and searchPosition.urgentlyHired != ''">
and p.urgently_hired = #{
searchPosition.urgentlyHired}
</if>
<if test="searchPosition.tagId != null and searchPosition.tagId != ''">
and p.tag_id = #{
searchPosition.tagId}
</if>
<if test="searchPosition.recruitmentName != null and searchPosition.recruitmentName != ''">
and r.name LIKE CONCAT('%',#{
searchPosition.recruitmentName},'%')
</if>
<if test="searchPosition.positionSource !=null and searchPosition.positionSource != ''">
and r.way = #{
searchPosition.positionSource}
</if>
<if test="searchPosition.status !=null and searchPosition.status != ''">
and r.status = #{
searchPosition.status}
</if>
</where>
order by p.create_ts desc
</select>
解决方案
问题出在count上,而count慢其实是因为联表,所以我选择重写count,利用if标签,避免联表,做条件查询的时候,由于做了筛选,数据量会小很多,所以不慢
<select id="getRecordPositionList_COUNT" resultType="Long">
SELECT count(*)
FROM position_record p
<if test="searchPosition.recruitmentName != null and searchPosition.recruitmentName != '' and searchPosition.positionSource !=null and searchPosition.positionSource != '' and searchPosition.status !=null and searchPosition.status != ''">
LEFT JOIN recruitment r ON p.recruitment_id = r.id
</if>
<if test="null != searchPosition.companyName and searchPosition.companyName != ''">
LEFT JOIN company c ON p.company_id = c.id
</if>
<where>
<if test="null != searchPosition.educationId and searchPosition.educationId != ''">
AND p.education_id = #{
searchPosition.educationId}
</if>
<if test="searchPosition.companyId != null and searchPosition.companyId != ''">
and p.company_id = #{
searchPosition.companyId}
</if>
<if test="searchPosition.positionName != null and searchPosition.positionName != ''">
and p.name LIKE CONCAT('%',#{
searchPosition.positionName},'%')
</if>
<if test="searchPosition.companyName != null and searchPosition.companyName != ''">
and c.name LIKE CONCAT('%',#{
searchPosition.companyName},'%')
</if>
<if test="searchPosition.startTime != null and searchPosition.endTime != null">
and p.release_ts<![CDATA[>=]]> #{
searchPosition.startTime}
and p.release_ts <![CDATA[<=]]> #{
searchPosition.endTime}
and p.status != '1'
</if>
<if test="searchPosition.createStartTs !=null ">
and p.create_ts <![CDATA[>=]]> #{
searchPosition.createStartTs}
</if>
<if test="searchPosition.createEndTs !=null ">
and p.create_ts <![CDATA[<=]]> #{
searchPosition.createEndTs}
</if>
<if test="searchPosition.property !=null and searchPosition.property != ''">
and p.property = #{
searchPosition.property}
</if>
<if test="searchPosition.salaryMax !=null and searchPosition.salaryMax != ''">
and p.salary_max <![CDATA[<=]]> #{
searchPosition.salaryMax}
</if>
<if test="searchPosition.salaryLower !=null and searchPosition.salaryLower != ''">
and p.salary_lower <![CDATA[>=]]> #{
searchPosition.salaryLower}
</if>
<if test="searchPosition.workingYearsId !=null and searchPosition.workingYearsId != ''">
and p.working_years_id = #{
searchPosition.workingYearsId}
</if>
<if test="searchPosition.sRegionId !=null and searchPosition.sRegionId != ''">
and p.s_region_id = #{
searchPosition.sRegionId}
</if>
<if test="searchPosition.urgentlyHired !=null and searchPosition.urgentlyHired != ''">
and p.urgently_hired = #{
searchPosition.urgentlyHired}
</if>
<if test="searchPosition.tagId != null and searchPosition.tagId != ''">
and p.tag_id = #{
searchPosition.tagId}
</if>
<if test="searchPosition.recruitmentName != null and searchPosition.recruitmentName != ''">
and r.name LIKE CONCAT('%',#{
searchPosition.recruitmentName},'%')
</if>
<if test="searchPosition.positionSource !=null and searchPosition.positionSource != ''">
and r.way = #{
searchPosition.positionSource}
</if>
<if test="searchPosition.status !=null and searchPosition.status != ''">
and r.status = #{
searchPosition.status}
</if>
</where>
</select>
使用方式
原有的代码不需要动,只需要在mybatis的xml文件里添加一个count查询
这里注意以下三点即可:
1.id和对应的查询语句保持一致,并且以 _COUNT 结尾,注意大小写
2.入参和对应的查询语句保持一致
3.出参为 resultType=“Long”
4.PageHelper的版本一定要在 5.0.5 以上