项目中统计SQL执行缓慢的方案-数据预处理
使用场景:
由于表数据量巨大,导致一些统计相关的sql执行非常慢,使用户有非常不好的体验,并且sql和数据库已经没有优化空间了。(并且该统计信息数据实时性要求不高的前提下)
解决方案:
整体思路:创建预处理表——通过定时任务将数据插入到结果表——统计信息时直接通过结果表进行查询——大大提高响应速度
注:1.结果表中需要包含查询条件里的所有字段
2.定时任务可以根据实际需要设定频率
3.最好创建一个与结果表表结构一样的临时表用于数据暂存,防止在插入数据这个时间段上导致结果表数据空白。(直接将临时表数据插入到结果表速度很快这段时间可以忽略)
方案示例:
第一步:创建结果表
drop table if exists `user_study_statistics`;
CREATE TABLE `project_statistics` (
`project_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '项目id',
`project_unit_id` int(11) NOT NULL COMMENT '单位工程id',
`unit_name` varchar(255) DEFAULT NULL COMMENT '单位工程名称',
`project_name` varchar(255) DEFAULT NULL COMMENT '项目名称',
`file_count` int(8) NOT NULL DEFAULT '0' COMMENT '文件总数',
`file_count_30` int(8) NOT NULL DEFAULT '0' COMMENT '文件总数(30天内)',
`file_count_90` int(8) NOT NULL DEFAULT '0' COMMENT '文件总数(90天内)',
`file_count_180` int(8) NOT NULL DEFAULT '0' COMMENT '文件总数(180天内)',
`check_count` int(8) DEFAULT NULL COMMENT '检查次数',
`check_count_30` int(8) DEFAULT NULL COMMENT '检查次数(30天内)',
`check_count_90` int(8) DEFAULT NULL COMMENT '检查次数(90天内)',
`check_count_180` int(8) DEFAULT NULL COMMENT '检查次数(180天内)',
`check_num` int(8) NOT NULL DEFAULT '0' COMMENT '检查文件总数',
`check_num_30` int(8) NOT NULL DEFAULT '0' COMMENT '检查文件总数(30天内)',
`check_num_90` int(8) NOT NULL DEFAULT '0' COMMENT '检查文件总数(90天内)',
`check_num_180` int(8) NOT NULL DEFAULT '0' COMMENT '检查文件总数(180天内)',
`check_scale` varchar(26) DEFAULT NULL COMMENT '检查文件占比',
`check_scale_30` varchar(26) DEFAULT NULL COMMENT '检查文件占比(30天内)',
`check_scale_90` varchar(26) DEFAULT NULL COMMENT '检查文件占比(90天内)',
`check_scale_180` varchar(26) DEFAULT NULL COMMENT '检查文件占比(180天内)',
`pass_scale` varchar(26) DEFAULT NULL COMMENT '通过率',
`pass_scale_30` varchar(26) DEFAULT NULL COMMENT '通过率(30天内)',
`pass_scale_90` varchar(26) DEFAULT NULL COMMENT '通过率(90天内)',
`pass_scale_180` varchar(26) DEFAULT NULL COMMENT '通过率(180天内)',
`correct_count` int(8) DEFAULT NULL COMMENT '整改条数',
`correct_count_30` int(8) DEFAULT NULL COMMENT '整改条数(30天内)',
`correct_count_90` int(8) DEFAULT NULL COMMENT '整改条数(90天内)',
`correct_count_180` int(8) DEFAULT NULL COMMENT '整改条数(180天内)',
`out_time_count` int(8) DEFAULT NULL COMMENT '逾期未完成整改条数',
`out_time_count_30` int(8) DEFAULT NULL COMMENT '逾期未完成整改条数(30天内)',
`out_time_count_90` int(8) DEFAULT NULL COMMENT '逾期未完成整改条数(90天内)',
`out_time_count_180` int(8) DEFAULT NULL COMMENT '逾期未完成整改条数(180天内)'
) ENGINE=InnoDB DEFAULT CHARSCREATE TABLE `project_statistics_tmp` (
`project_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '项目id',
`project_unit_id` int(11) NOT NULL COMMENT '单位工程id',
`unit_name` varchar(255) DEFAULT NULL COMMENT '单位工程名称',
`project_name` varchar(255) DEFAULT NULL COMMENT '项目名称',
`file_count` int(8) NOT NULL DEFAULT '0' COMMENT '文件总数',
`file_count_30` int(8) NOT NULL DEFAULT '0' COMMENT '文件总数(30天内)',
`file_count_90` int(8) NOT NULL DEFAULT '0' COMMENT '文件总数(90天内)',
`file_count_180` int(8) NOT NULL DEFAULT '0' COMMENT '文件总数(180天内)',
`check_count` int(8) DEFAULT NULL COMMENT '检查次数',
`check_count_30` int(8) DEFAULT NULL COMMENT '检查次数(30天内)',
`check_count_90` int(8) DEFAULT NULL COMMENT '检查次数(90天内)',
`check_count_180` int(8) DEFAULT NULL COMMENT '检查次数(180天内)',
`check_num` int(8) NOT NULL DEFAULT '0' COMMENT '检查文件总数',
`check_num_30` int(8) NOT NULL DEFAULT '0' COMMENT '检查文件总数(30天内)',
`check_num_90` int(8) NOT NULL DEFAULT '0' COMMENT '检查文件总数(90天内)',
`check_num_180` int(8) NOT NULL DEFAULT '0' COMMENT '检查文件总数(180天内)',
`check_scale` varchar(26) DEFAULT NULL COMMENT '检查文件占比',
`check_scale_30` varchar(26) DEFAULT NULL COMMENT '检查文件占比(30天内)',
`check_scale_90` varchar(26) DEFAULT NULL COMMENT '检查文件占比(90天内)',
`check_scale_180` varchar(26) DEFAULT NULL COMMENT '检查文件占比(180天内)',
`pass_scale` varchar(26) DEFAULT NULL COMMENT '通过率',
`pass_scale_30` varchar(26) DEFAULT NULL COMMENT '通过率(30天内)',
`pass_scale_90` varchar(26) DEFAULT NULL COMMENT '通过率(90天内)',
`pass_scale_180` varchar(26) DEFAULT NULL COMMENT '通过率(180天内)',
`correct_count` int(8) DEFAULT NULL COMMENT '整改条数',
`correct_count_30` int(8) DEFAULT NULL COMMENT '整改条数(30天内)',
`correct_count_90` int(8) DEFAULT NULL COMMENT '整改条数(90天内)',
`correct_count_180` int(8) DEFAULT NULL COMMENT '整改条数(180天内)',
`out_time_count` int(8) DEFAULT NULL COMMENT '逾期未完成整改条数',
`out_time_count_30` int(8) DEFAULT NULL COMMENT '逾期未完成整改条数(30天内)',
`out_time_count_90` int(8) DEFAULT NULL COMMENT '逾期未完成整改条数(90天内)',
`out_time_count_180` int(8) DEFAULT NULL COMMENT '逾期未完成整改条数(180天内)'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='项目检查状态统计表';
ET=utf8 COMMENT='项目检查状态统计表_临时表';
创建视图:
CREATE VIEW `v_project_statistics_info` AS
SELECT project_id,project_unit_id,unit_name,project_name,
COUNT(1) file_count,-- 文件总数
COUNT((datediff(date(now()),date(gmt_create)) <=30 ) OR null) file_count_30,
COUNT((datediff(date(now()),date(gmt_create)) <=90 ) OR null) file_count_90,
COUNT((datediff(date(now()),date(gmt_create)) <=180 ) OR null) file_count_180,
SUM(check_count) as check_count,-- 检查次数
SUM(CASE WHEN (datediff(date(now()),date(modify_time)) <=30 ) THEN check_count ELSE 0 END) AS check_count_30,
SUM(CASE WHEN (datediff(date(now()),date(modify_time)) <=90 ) THEN check_count ELSE 0 END) AS check_count_90,
SUM(CASE WHEN (datediff(date(now()),date(modify_time)) <=180 ) THEN check_count ELSE 0 END) AS check_count_180,
COUNT(check_count>0 OR null) as check_num,-- 检查文件总数
COUNT((datediff(date(now()),date(modify_time)) <=30 ) and check_count>0 OR null) as check_num_30,
COUNT((datediff(date(now()),date(modify_time)) <=90 ) and check_count>0 OR null) as check_num_90,
COUNT((datediff(date(now()),date(modify_time)) <=180 ) and check_count>0 OR null) as check_num_180,
CONCAT(ROUND(COUNT(check_count>0 OR null)/COUNT(1)*100,0),'%') as check_tage, -- 检查文件占比
CONCAT(ROUND(COUNT((datediff(date(now()),date(modify_time)) <=30 ) and check_count>0 OR null)/COUNT((datediff(date(now()),date(gmt_create)) <=30 ) OR null)*100,0),'%') as check_scale_30,
CONCAT(ROUND(COUNT((datediff(date(now()),date(modify_time)) <=90 ) and check_count>0 OR null)/COUNT((datediff(date(now()),date(gmt_create)) <=90 ) OR null)*100,0),'%') as check_scale_90,
CONCAT(ROUND(COUNT((datediff(date(now()),date(modify_time)) <=180 ) and check_count>0 OR null)/COUNT((datediff(date(now()),date(gmt_create)) <=180 ) OR null)*100,0),'%') as check_scale_180,
CONCAT(ROUND(COUNT(check_status=2 OR null)/COUNT(check_count>0 OR null)*100,0),'%') as pass_tage, -- 通过率
CONCAT(ROUND(COUNT((datediff(date(now()),date(modify_time)) <=30 ) and check_status=2 OR null)/COUNT((datediff(date(now()),date(modify_time)) <=30 ) and check_count>0 OR null)*100,0),'%') as pass_scale_30,
CONCAT(ROUND(COUNT((datediff(date(now()),date(modify_time)) <=90 ) and check_status=2 OR null)/COUNT((datediff(date(now()),date(modify_time)) <=90 ) and check_count>0 OR null)*100,0),'%') as pass_scale_90,
CONCAT(ROUND(COUNT((datediff(date(now()),date(modify_time)) <=180 ) and check_status=2 OR null)/COUNT((datediff(date(now()),date(modify_time)) <=180 ) and check_count>0 OR null)*100,0),'%') as pass_scale_180,
SUM(correct_count) as correct_count,-- 整改条数
SUM(correct_count_30) as correct_count_30,
SUM(correct_count_90) as correct_count_90,
SUM(correct_count_180) as correct_count_180,
SUM(out_time_count) as out_time_count, -- 逾期未完成整改条数
SUM(out_time_count_30) as out_time_count_30,
SUM(out_time_count_90) as out_time_count_90,
SUM(out_time_count_180) as out_time_count_180
from (
SELECT SUBSTRING_INDEX(d.bus_id,'_',1) as project_id,d.project_unit_id,d.node_id,ifnull(d.check_count,0) as check_count,d.check_status,ifnull(a.correct_count,0) as correct_count,ifnull(a.correct_count_30,0) as correct_count_30,ifnull(a.correct_count_90,0) as correct_count_90,ifnull(a.correct_count_180,0) as correct_count_180,ifnull(a.out_time_count,0) as out_time_count,ifnull(a.out_time_count_30,0) as out_time_count_30,ifnull(a.out_time_count_90,0) as out_time_count_90,ifnull(a.out_time_count_180,0) as out_time_count_180,u.unit_name,p.project_name,d.modify_time,d.gmt_create from v_doc_info d
INNER JOIN project_detail p on p.local_project_id=d.project_id
LEFT JOIN project_unit u on u.id=d.project_unit_id
left join(
SELECT local_project_id,IFNULL(correct_soure_id,0)as node_id,COUNT(1) as correct_count
,COUNT(datediff(date(now()),date(create_time)) <=30) as correct_count_30
,COUNT(datediff(date(now()),date(create_time)) <=90) as correct_count_90
,COUNT(datediff(date(now()),date(create_time)) <=180) as correct_count_180
,count((have_deleted=0 and correct_end_time<NOW()) or null) as out_time_count
,count((have_deleted=0 and correct_end_time<NOW() and (datediff(date(now()),date(create_time)) <=30)) or null) as out_time_count_30
,count((have_deleted=0 and correct_end_time<NOW() and (datediff(date(now()),date(create_time)) <=90)) or null) as out_time_count_90
,count((have_deleted=0 and correct_end_time<NOW() and (datediff(date(now()),date(create_time)) <=180)) or null) as out_time_count_180 from doc_correct GROUP BY local_project_id,correct_soure_id
) a on a.node_id=d.node_id
UNION ALL
SELECT d.project_id,d.remote_project_id as project_unit_id,d.id as node_id,ifnull(d.check_count,0) as check_count,d.check_status,ifnull(a.correct_count,0) as correct_count,ifnull(a.correct_count_30,0) as correct_count_30,ifnull(a.correct_count_90,0) as correct_count_90,ifnull(a.correct_count_180,0) as correct_count_180,ifnull(a.out_time_count,0) as out_time_count,ifnull(a.out_time_count_30,0) as out_time_count_30,ifnull(a.out_time_count_90,0) as out_time_count_90,ifnull(a.out_time_count_180,0) as out_time_count_180,u.unit_name,p.project_name,d.modify_time,d.gmt_create from v_datumdata_info d
INNER JOIN project_detail p on p.local_project_id=d.project_id
LEFT JOIN project_unit u on u.id=d.remote_project_id
left join(
SELECT local_project_id,IFNULL(correct_soure_id,0)as node_id,COUNT(1) as correct_count
,COUNT(datediff(date(now()),date(create_time)) <=30) as correct_count_30
,COUNT(datediff(date(now()),date(create_time)) <=90) as correct_count_90
,COUNT(datediff(date(now()),date(create_time)) <=180) as correct_count_180
,count((have_deleted=0 and correct_end_time<NOW()) or null) as out_time_count
,count((have_deleted=0 and correct_end_time<NOW() and (datediff(date(now()),date(create_time)) <=30)) or null) as out_time_count_30
,count((have_deleted=0 and correct_end_time<NOW() and (datediff(date(now()),date(create_time)) <=90)) or null) as out_time_count_90
,count((have_deleted=0 and correct_end_time<NOW() and (datediff(date(now()),date(create_time)) <=180)) or null) as out_time_count_180 from doc_correct GROUP BY local_project_id,correct_soure_id
) a on a.node_id=d.id
)t GROUP BY project_id,project_unit_id
第二步:创建预处理定时任务
/**
* 资料检查统计预加载定时任务
*/
@PostConstruct //程序启动时就执行一次
@Scheduled(cron = "${schedul.statistics.checkStatistics:0 0 * * * ?}") //默认定时频率每小时执行一次
public void preProjectStatistics(){
//0.删除临时表里的数据
statisticsDao.deleteStatisticsTmpData();
//1.将数据插入临时表
statisticsDao.insertStatisticsTmpData();
//2.删除正式表里的数据
statisticsDao.deleteStatisticsData();
//3.将临时表里的数据插入正式表
statisticsDao.insertStatisticsData();
//3.删除临时表里的数据
statisticsDao.deleteStatisticsTmpData();
}
对应的sql语句:
<insert id="insertStatisticsTmpData">
insert into project_statistics_tmp SELECT * from v_project_statistics_info
</insert>
<delete id="deleteStatisticsData" parameterType="java.lang.Long">
delete from project_statistics;
</delete>
<insert id="insertStatisticsData">
insert into project_statistics
select * from project_statistics_tmp;
</insert>
<delete id="deleteStatisticsTmpData" parameterType="java.lang.Long">
delete from project_statistics_tmp;
</delete>
第三步: 修改之前的统计sql从多表关联到查询单表速度有了质的提升
博客园排版可能有点乱,可转至我个人链接地址:https://raokun.top/raokun/archives/项目中统计sql执行缓慢的方案-数据预处理
项目中统计SQL执行缓慢的方案-数据预处理的更多相关文章
- Oracle SQL执行缓慢的原因以及解决方案
以下的文章抓哟是对Oracle SQL执行缓慢的原因的分析,如果Oracle数据库中的某张表的相关数据已是2亿多时,同时此表也创建了相关的4个独立的相关索引.由于业务方面的需要,每天需分两次向此表中 ...
- VS Code项目中共享自定义的代码片段方案
VS Code项目中共享自定义的代码片段方案 一.问题背景 项目中注释风格不统一,如何统一注释风格 一些第三方组件库名称太长,每次使用都需要找文档,然后复制粘贴 部分组件库有自己的Snippets插件 ...
- hint不当索引,影响多表连接方式,最终导致SQL执行缓慢
需求:一个SQL执行特别慢,无法返回结果,需要进行优化,最终返回结果即可. 一.SQL分析 二.尝试执行,观测执行计划 三.修改SQL 四.问题总结 一.SQL分析 )SQL文本,执行时间,执行用户 ...
- vue项目中引入循环执行setInterval或者requestAnimationFrame的用法等
项目中循环计时处理某些方法的情况还是比较常见的,一般会用setInterval来处理,但是这个方法会似的页面卡顿等使用体验不好. 所以就使用浏览器提供的requestAnimationFrame方法, ...
- 在EF中使用SQL执行简单高效的增删查操作
随着平台数据的积累,对于数据访问的速度要求愈来愈高.优化后台访问性能,将是之后的一个重点任务. 但是,后台在项目开发初期采用的是Abp(Lite DDD)框架,集成EnityFramework.因为之 ...
- 项目中常用SQL语句总结
1.项目中常常需要修改字段长度,但需要保留数据--增加业务受理 项目名称 字段长度alter table t_ywsl add aa varchar2(200);update t_ywsl set a ...
- plsql中查看sql执行计划
想要优化sql语句,可以从sql执行计划入手. 在plsql客户端,提供了一个方便的按钮来查看执行计划 选中需要查看的sql语句,点击此按钮,就可以看到该条语句的执行计划了. 结果集包括描述,用户,对 ...
- BI项目中的ETL设计详解(数据抽取、清洗与转换 )(转载)
原文:http://www.cnblogs.com/reportmis/p/5939732.html ETL是BI项目最重要的一个环节,通常情况下ETL会花掉整个项目的1/3的时间,ETL设计的好坏直 ...
- Django项目中如何建表?怎样导入数据?
http://django-chinese-docs.readthedocs.org/en/latest/topics/db/models.html 通常在项目中的models.py文件中建表的 Th ...
- sqlplus中显示sql执行计划和统计信息
31 ,32 , 33 ,34 keywords : oracle storage structure 最详细讲解: 1:doc 1 logical storage structure 2 ...
随机推荐
- PHP中获取时间的下一周下个月的方法
PHP中获取时间的下一周,下个月等通常用于定制服务的时候使用,比如包月会员,包年等等 //通常用于定制服务的时候使用,比如包月会员,包年等等 //获取当前时间过一个月的时间,以DATETIME格式显示 ...
- logstash从MySQL导入数据到ES
下载安装 一定要对应ES版本(5.x,6.x,7.x) win下不用安装解压即用 , 解压目录不能带有空格和中文 , 否则会有奇奇怪怪的报错无法运行 win下要给logstash文件夹赋予管理员权限 ...
- wmware桥接模式
配置思路(桥接模式) 准备一个与PC机同网段且未被占用的IP地址 将虚拟机的网络模式修改为桥接模式(默认为NAT模式) 修改网卡配置文件,配置为准备好的IP地址,并重启网络服务. 配置DNS解析服务器 ...
- vue下拉选择select option el-cascader删除重选值的问题
select当下拉值多的时候 以及input cascader级联选择一个值后 后面我不想要了 vue 提供了一个关键字 可以帮你全部清空 这个关键字就是:clearable
- Javaweb学习笔记第五弹
preparedStatement 防止SQL注入:将敏感字符进行转义 1.获取PreparedStatement对象 String sql="selct * from 表名 where 列 ...
- PyQt-Fluent-Widgets:一个 Fluent Design 风格的组件库
简介 这是一个使用 PyQt/PySide 编写的 Fluent Design 风格的组件库,包含最常用的组件,支持亮暗主题无缝切换.实际上此项目是从 Groove Music 项目剥离出来的子项目, ...
- 【开源免费】使用Spring Boot和Html实现ChatGPT,1:亿还原,将就看
highlight: a11y-dark 简介 前段时间写了一个Chatgpt的Java版SDK开源地址:chatgpt-java欢迎使用.但由于原来OpenAI 并没有支持官网的chatgpt模型, ...
- 帮你积累音视频知识,Agora 开发者漫游指南正式启航
"运气是设计的残留物."--John Milton 如果玩过<全面战争:中世纪 II>,或者读过 John Milton 书的人,可能对这句话有印象.我们发现,很多小伙 ...
- 微软wsl2启用天父行程systemd
默认情况下 微软wsl2的天父行程是init,没办法使用systemctl相关指令,所以想使用天父行程 systemd. 本文以Wsl2 Alma Linux为例,启用systemd 上帝与你同在,阿 ...
- 学习ASP.NET Core Blazor编程系列三十——JWT登录(4)
学习ASP.NET Core Blazor编程系列文章之目录 学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应 ...