在Activiti工作流引擎项目Saas改造中,会遇到说多租户多用户的情况,那么每个表单数据量也会变多,单表百万级需求就成为一个必须要解决的问题。
别说可以用分库分表的方案,分库分表已经解决了千万级大表数据的情况了,总不能总是依赖数据库中间件分库分表方案,因为该方案分片是需要预先设定好的,如果改动分片策略或者分片数量,需要重新导数据,十分麻烦。那么使单表能够支持多一些数据的查询就尤为重要,尤其是流程引擎项目中设计到很多的关联查询,如下:
sql=
select F0000001,CreatedTime,a.act_result as actResult, (select user_name from sys_user su WHERE su.id=a.start_user_Id) As startUserId, a.start_user_name as startUserName, (SELECT GROUP_CONCAT(distinct user_name) from sys_user su LEFT JOIN ru_wf_task rwt ON su.id = rwt.deal_id WHERE rwt.app_run_id=a.id and rwt.status='1') as assignee, (select GROUP_CONCAT(distinct deal_name) from ru_wf_task rwt where rwt.app_run_id = a.id and rwt.status = '1') as assigneeName, a.id as appRunId,a.instance_id as instanceId,a.name_schema as Name,a.id as ObjectId, a.start_time as startTime from t_6e676bef4b68ddceb826429b8db311f1 t left join ru_wf_apprun a on a.id = t.app_run_id where a.app_id = 'b4cffb1a1a234d2eb673c2b33c30a7e8462383049' and t.company_id = '1' order by create_time desc
十分蛋疼,在百万级单库t_6e676bef4b68ddceb826429b8db311f1里面要跑138s,前端早就卡死了噢,但是这个分页需求,使用mybatis的pagehelper后面还要在sql后面加上Limit 0,10。
分页sql
select F0000001,CreatedTime,a.act_result as actResult, (select user_name from sys_user su WHERE su.id=a.start_user_Id) As startUserId, a.start_user_name as startUserName, (SELECT GROUP_CONCAT(distinct user_name) from sys_user su LEFT JOIN ru_wf_task rwt ON su.id = rwt.deal_id WHERE rwt.app_run_id=a.id and rwt.status='1') as assignee, (select GROUP_CONCAT(distinct deal_name) from ru_wf_task rwt where rwt.app_run_id = a.id and rwt.status = '1') as assigneeName, a.id as appRunId,a.instance_id as instanceId,a.name_schema as Name,a.id as ObjectId, a.start_time as startTime from t_6e676bef4b68ddceb826429b8db311f1 t left join ru_wf_apprun a on a.id = t.app_run_id where a.app_id = 'b4cffb1a1a234d2eb673c2b33c30a7e8462383049' and t.company_id = '1' order by create_time desc limit 0,10
单独执行这个语句,大概1.8s其实还算能接受了,相比原来,但是pagehelper插件需要做一个select count(0) from (" + sql + ")as total的操作,这个操作会遍历全表,那就非常慢了,关键是sql就要138s了,再count怎么行。其实分析这个语句的目的就能发现,count最后只是返回一个数字而已,那么sql是不是可以优化一下使count更快一点呢?可以参考
https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/Changelog.md
5.0.4版本已经添加了手写count支持。
然后我把sql优化一下,去掉不必要的查询,count语句为
select count(0) from (select 0 from t_6e676bef4b68ddceb826429b8db311f1 t left join ru_wf_apprun a on a.id = t.app_run_id where a.app_id = 'b4cffb1a1a234d2eb673c2b33c30a7e8462383049' and t.company_id = '1' )as total;
运行耗时5.9s,已经可以勉强接受了,配合分库分表方案,可以支撑Saas环境下的大数据量了。后面想到还有哪些优化再写吧。

针对Activiti工作流引擎在SaaS环境下多租户、多用户场景中出现的单表百万级数据查询问题,本文详细介绍了如何优化复杂关联查询的SQL语句,通过减少不必要的字段查询和利用PageHelper的手写count支持,将查询时间从138秒降低至可接受范围,有效提升系统性能。
1386

被折叠的 条评论
为什么被折叠?



