项目中统计SQL执行缓慢的方案-数据预处理

项目,统计,sql,执行,缓慢,方案,数据,预处理 · 浏览次数 : 25

小编点评

内容生成时需要带简单的排版,以下是一些例子: 1. **设置时间参数** ```java @Scheduled(cron = "00:15") public void setTime(){ //设置时间 } ``` 2. **设置排版语句** ```java //设置多个排版语句 statisticsDao.deleteStatisticsTmpData(); statisticsDao.insertStatisticsTmpData(); ``` 3. **设置多个条件** ```java //设置多个条件 if (statisticsDao.isExistsStatisticsTmpData()) { //进行操作 } ``` 4. **设置多个变量** ```java //设置多个变量 String name = "raokun"; int age = 30; ``` 5. **设置多个条件并设置多个变量** ```java //设置多个条件并设置多个变量 if (statisticsDao.isExistsStatisticsTmpData() && name.equals("raokun") && age == 30) { //进行操作 } ``` 6. **设置复杂条件** ```java //设置复杂条件 if (statisticsDao.isExistsStatisticsTmpData() && name.equals("raokun") && age == 30 && statisticsDao.isExistsStatisticsData()) { //进行操作 } ``` 7. **设置多个条件并设置多个变量** ```java //设置多个条件并设置多个变量 if (statisticsDao.isExistsStatisticsTmpData() && name.equals("raokun") && age == 30 && statisticsDao.isExistsStatisticsData()) { //进行操作 } ``` 8. **设置复杂条件并设置多个变量** ```java //设置多个条件并设置多个变量 if (statisticsDao.isExistsStatisticsTmpData() && name.equals("raokun") && age == 30 && statisticsDao.isExistsStatisticsData()) { //进行操作 } ```

正文

使用场景:
由于表数据量巨大,导致一些统计相关的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执行缓慢的方案-数据预处理相似的内容:

项目中统计SQL执行缓慢的方案-数据预处理

使用场景: 由于表数据量巨大,导致一些统计相关的sql执行非常慢,使用户有非常不好的体验,并且sql和数据库已经没有优化空间了。(并且该统计信息数据实时性要求不高的前提下) 解决方案: 整体思路:创建预处理表——通过定时任务将数据插入到结果表——统计信息时直接通过结果表进行查询——大大提高响应速度

mysql查询上个季度数据

mysql查询上季度数据 最近接口需要统计上个季度的数据统计,补一下sql 季度函数: QUARTER(date) 函数返回给定日期值(1到4之间的数字)的一年中的季度 语法: QUARTER(date) | 参数 | 描述 | | | | | date | 必须项。从中提取季度的日期或日期时间 |

使用Java统计gitlab代码行数

一、背景: 需要对当前公司所有的项目进行代码行数的统计 二、 可实现方式 1.脚本:通过git脚本将所有的项目拉下来并然后通过进行代码行数的统计 样例: echo 创建项目对应的文件夹 mkdir 项目名称echo 切到创建的文件夹中 cd 项目名称echo 进行git初始化 git init ec

go项目实现通过配置文件进行配置项统一管理

转载请注明出处: go项目中实现配置项统一管理,实现逻辑:将 配置项整理为一个json的数据结构,并保存到go.conf文件中,然后在go项目启动main方法中加载 go.conf 文件,读取go.conf 文件的json 数据结构,并进行反序列化为go的数据结构,从而在go项目中可以全局使用 go

从0到1构建基于自身业务的前端工具库

在实际项目开发中无论 M 端、PC 端,或多或少都有一个 utils 文件目录去管理项目中用到的一些常用的工具方法,比如:时间处理、价格处理、解析url参数、加载脚本等,其中很多是重复、基础、或基于某种业务场景的工具,存在项目间冗余的痛点以及工具方法规范不统一的问题

Vue 3与ESLint、Prettier:构建规范化的前端开发环境

这篇文章介绍了如何在Vue 3项目中配置ESLint和Prettier以统一代码风格,实现代码规范性与可读性的提升。通过设置规则、解决冲突、以及将配置融入持续集成流程和代码审查过程,确保团队协作时代码风格的一致性,提升开发效率与项目维护性。

在基于vue-next-admin的Vue3+TypeScript前端项目中,为了使用方便全局挂载对象接口

在基于vue-next-admin 的 Vue3+TypeScript 前端项目中,可以整合自己的 .NET 后端,前端操作一些功能的时候,为了使用方便全局挂载的对象接口,以便能够快速处理一些特殊的操作,如消息提示、辅助函数、正则测试等等。本篇随笔介绍在Vue3+TypeScript 前端项目中全局挂载对象$u,获得相关 $u_interface 的统一入口的接口信息。这样在组件或者页面中就可以方

从 5s 到 0.5s!CompletableFuture 异步任务优化技巧,确实优雅!

一个接口可能需要调用 N 个其他服务的接口,这在项目开发中还是挺常见的。举个例子:用户请求获取订单信息,可能需要调用用户信息、商品详情、物流信息、商品推荐等接口,最后再汇总数据统一返回。 如果是串行(按顺序依次执行每个任务)执行的话,接口的响应速度会非常慢。考虑到这些接口之间有大部分都是 无前后顺序

OpenVoiceV2本地部署教程,苹果MacOs部署流程,声音响度统一,文字转语音,TTS

最近OpenVoice项目更新了V2版本,新的模型对于中文推理更加友好,音色也得到了一定的提升,本次分享一下如何在苹果的MacOs系统中本地部署OpenVoice的V2版本。 首先下载OpenVoiceV2的压缩包: OpenVoiceV2-for-mac代码和模型 https://pan.quar

在C#中使用RabbitMQ做个简单的发送邮件小项目

在C#中使用RabbitMQ做个简单的发送邮件小项目 前言 好久没有做项目了,这次做一个发送邮件的小项目。发邮件是一个比较耗时的操作,之前在我的个人博客里面回复评论和友链申请是会通过发送邮件来通知对方的,不过当时只是简单的进行了异步操作。 那么这次来使用RabbitMQ去统一发送邮件,我的想法是通过