前段时间压力山大,为了提高程序的性能和稳定性,需要对基于springcloud的微服务平台进行性能压测。由于时间的紧迫性,我们只对关键的几十个api接口以及网关进行了压测,对于压测的结果,我发现一个有意思的地方:大部分api接口性能不达标源于大sql查询慢,而且是随着时间的推移,数据越多查询越慢。
看几个我们项目真实的例子
1、获取新闻列表api接口
<select id="queryList" resultMap="BaseResultMap">
select t.*,ac.*,u.user_truename as username,f.content as flowContent ,f.flow_type as flowType ,d.dept_id as
deptid, d.org_name as prodeptName, c.name as categoryname ,pc.name as pcategoryname from cms_article t
left join cms_template_flow f on t.template_flow_id=f.template_flow_id
left join sys_user u on t.create_user_id =u.user_id
left join sys_dept d on d.dept_id =t.prodeptid
left join cms_category c on t.category_id=c.id
left join cms_category pc on pc.id=c.parent_id
left join ms_article_count ac on ac.article_id=t.id
<where>
...
</where>
</select>
为了获取新闻列表结果,需要文章表(cms_article)左关联文章模板表(cms_template_flow),用户表(sys_user),机构表(sys_dept),文章频道分类表(cms_category)、文章评论点赞统计表(ms_article_count)共7张表,其中文章表、评论点赞统计表随着时间的推移,数据量以千万级甚至亿级来计算,显然上面的大sql性能肯定不符合要求。
2、新闻详情api接口
<select id="queryObject" resultMap="BaseResultMap">
select t.*,u.user_truename as username,c.name as categoryname,f.content as flowContent,f.flow_type as flowType ,
c.dept_id as cdeptid ,d.dept_id as deptid, d.org_name as deptname,d1.org_name as prodeptName,pc.name as pcategoryname,pc.id as pcategoryid,
sdt.ITEM_NAME as sfromname ,sd.DICT_NAME as ffromname
from `cms_article` t
left join sys_user u on t.create_user_id =u.user_id
left join sys_dict_item sdt on t.sfrom = sdt.ITEM_NO
left join sys_dict sd on t.ffrom = sd.DICT_NO
left join sys_dept d on d.dept_id =t.deptid
left join sys_dept d1 on d1.dept_id =t.prodeptid
left join cms_category c on t.category_id =c.id
left join cms_category pc on pc.id=c.parent_id
left join cms_template_flow f on t.template_flow_id=f.template_flow_id
where
t.id = #{id}
</select>
新闻详情接口需要文章表(cms_article)左关联字典表(sys_dict、sys_dict_item)、用户表(sys_user),机构表(sys_dept),文章频道分类表(cms_category),文章模板表(cms_template_flow)同样存在数据量越大sql查询越慢的问题。
大sql特征
早期数据库数据量小时,用户感知不到页面查询慢。但是随着时间的推移,数据量逐渐增多,数据库sql查询慢的问题会变得非常突出,这是我们不愿意看到的,所以我们在实际的项目中做了4种切实可行的sql以及程序优化。
一、表字段冗余设计
例如文章表需要关联用户表的userid字段,那我们可以把userid字段添加到文章表,这样减少与用户表关联查询。
二、利用redis做二级缓存查询
对于无需分页的数据,我们可以利用redis的set/get方式缓存数据,部分数据可以设置过期时间。
redis设置过期时间
redisClient.setex(key, 10 * 60, jsonValue);
redis获取数据
String key = "pcm:news:getRelatedNews:" + getUserId() + ":" + getPath().replace(",", "")+":" +aid+":"+wid;
String jsonValue = redisClient.get(key);
三、合理创建表字段索引
建议一个表创建索引的数量在4个左右,合理在查询频繁的字段上建立索引可以大大提高sql的查询性能。
四、利用搜索引擎:elasticsearch、mongodb
对于查询数据量大,又需要实时查询的数据,可以elasticsearch和mongodb做搜索引擎,它们天生适合大数据查询。
诊断sql
sql调优
慢sql的产生不单单是sql代码和程序本身的问题,更多需要从架构、业务、服务器、网络等多方面去排查和分析具体原因 。
如果觉得本文对您有帮助的话,记得关注、转发哦,我会为大家持续提供原创干货。需要资料,请关注、转发,私信“资料”面试+微服务+springboot资料免费赠送。
留言与评论(共有 0 条评论) |