项目中发现有一个查询响应非常慢,花时间分析以及优化,特地记录。 (1)背景项目采用MySQL数据库,操作使用Ibatis;(2)查询说明这个查询是每次查询一定数目的用户信息,查询中涉及到多表关联,具体查询SQL如下
- <select id="select" parameterClass="UserCompany" resultClass="UserCompany">
- SELECT S.NAME as name,
- S.IMAGE as image,
- S.ID as id,
- C.NAME as companyName,
- C.ID as companyId,
- A.FILE_NAME AS resourceFileName,
- A.FILE_PATH AS resourceFilePath,
- A.FILE_ID AS resourceFileId,
- COUNT(R.CONTACT) AS updResourceSize
- from sys_user_info S
- LEFT JOIN ATTACH_FILE_INFO A ON S.ID = A.USER_ID
- LEFT JOIN
- (SELECT RESOURCE_ID,CONTACT FROM company_resource_info
- WHERE UPDTIME >= #UPDResourceTime:TIMESTAMP# ) R
- ON S.ID = R.CONTACT,
- company_info C
- WHERE S.COMPANY_ID = C.ID
- GROUP BY S.ID
- LIMIT 15
- </select>
注意其中用到了子查询,涉及到临时表 (3)分析过程使用MySQL自带的profiler分析结果如下图
观察可得,99%的时间花在了拷贝数据到临时表上,也就是与其中的子查询有关系。想来奇怪,如果只是LIMIT 15条数据,临时数据不应该花费这么多时间;个人觉得问题应该出在LIMIT对于里面的子查询无效,也就是里面的子查询会涉及到全部数据,从而导致临时表消耗很大的时间,这样就不难理解了。(4)优化想清楚了上面的原因,解决的思路也就比较清楚了,只要让里面涉及的子查询只查LIMIT对应的数据就可以了。重新实行的方式如下:
- <resultMap class="cn.com.steel.wuyou.model.UserCompany" id="UserCompanyMap">
- <result property="name" column="name" />
- <result property="image" column="image" />
- <result property="id" column="id" />
- <result property="companyName" column="companyName" />
- <result property="companyId" column="companyId" />
- <result property="resourceFileName" column="resourceFileName" />
- <result property="resourceFilePath" column="resourceFilePath" />
- <result property="resourceFileId" column="resourceFileId" />
- <result property="UPDResourceTime" column="UPDResourceTime" />
- <result property="updResourceSize" column="{CONTACT=id,udpResourceTime=UPDResourceTime}"
- select="steel_userCompany.selectUpdResourceSize" />
- </resultMap>
-
- <select id="selectUpdResourceSize" parameterClass="java.util.HashMap"
- resultClass="int">
- SELECT COUNT(1) FROM company_resource_info
- WHERE CONTACT = #CONTACT#
- and UPDTIME >= #UPDResourceTime:TIMESTAMP#
- </select>
-
-
- <select id="select" parameterClass="UserCompany" resultMap="UserCompanyMap">
- SELECT S.NAME as name,
- S.IMAGE as image,
- S.ID as id,
- C.NAME as companyName,
- C.ID as companyId,
- A.FILE_NAME AS resourceFileName,
- A.FILE_PATH AS resourceFilePath,
- A.FILE_ID AS resourceFileId,
- #UPDResourceTime:TIMESTAMP# as UPDResourceTime
- from sys_user_info S
- LEFT JOIN ATTACH_FILE_INFO A ON S.ID = A.USER_ID
- LEFT JOIN company_info C ON S.COMPANY_ID = C.ID
- LIMIT 15
- </select>
主要的做法就是,每次先查出LIMIT 15条不含子查询结果的数据,定义一个resultMap映射结果集,针对每一条记录再去分别调用一次查询从而得到最后想要的结果。
MySQL查询第几行到第几行记录数据库连接查询相关资讯 MySQL教程 MySQL使用教程
- MySQL使用教程图文详解 (05月22日)
- MySQL教程:关于checkpoint机制 (01月24日)
- MySQL::Sandbox (04/14/2013 08:03:38)
| - 30分钟带你快速入门MySQL教程 (02月03日)
- MySQL教程:关于I/O内存方面的一些 (01月24日)
- CentOS上开启MySQL远程访问权限 (01/29/2013 10:58:40)
|
本文评论 查看全部评论 (0)