首页 > 数据库 >SQL调优:让Java内存分担计算

SQL调优:让Java内存分担计算

时间:2023-06-18 21:37:44浏览次数:77  
标签:queryWrapper Java mav List 博客 查询 调优 SQL id


作者: 剽悍一小兔


我们在工作中,经常会因为一条慢sql调半天。这一节,我给大家介绍一种提升查询效率的思路,那就是让Java内存帮我们分担一些运算。

案例还是采用 springBoot日记本系统,源码下载地址和教程在文末。

先改一个BUG

之前遗留了一个BUG需要我们解决,就是在日记的详情页,日记类型没有做转换。

SQL调优:让Java内存分担计算_List

让我们看下controller:

@RequestMapping("diary/{id}.html")
@SaCheckLogin
public ModelAndView getDiary(@PathVariable Long id, ModelAndView mav){
    TblSynBlog tblSynBlog = blogService.selectOne(id);
    mav.addObject("blog",tblSynBlog);
    mav.addObject("statistics",blogService.getBlogsStatistics());
    mav.setViewName("detail");
    return mav;
}

破案了,代码中直接把tblSynBlog放到了modelAndView中,没有对Type进行专门的处理。

现在开始改BUG:

思路很简单,根据日记的type去类型表查询具体的中文是啥,再返回就可以了。

@RequestMapping("diary/{id}.html")
@SaCheckLogin
public ModelAndView getDiary(@PathVariable Long id, ModelAndView mav){
    TblSynBlog tblSynBlog = blogService.selectOne(id);
    //对Type进行中文转义
    SysBlogType type = sysBlogTypeService.getByTypeId(tblSynBlog.getBlogType());
    mav.addObject("blogType",type.getTypeName());

    mav.addObject("blog",tblSynBlog);
    mav.addObject("statistics",blogService.getBlogsStatistics());
    mav.setViewName("detail");
    return mav;
}

ISysBlogTypeService

SysBlogType getByTypeId(String blogType);

SysBlogTypeServiceImpl

@Override
public SysBlogType getByTypeId(String blogType) {
    return baseMapper.selectById(Integer.parseInt(blogType));
}

我们一般不推荐直接在controller引入mapper,这是规范,还是老老实实写service吧。

detail.jsp

<div class="title2">发布时间:${blog.createDate}     日志类别:${blogType}</div>

成果

SQL调优:让Java内存分担计算_开发语言_02

搞定。

新需求

刚才的一套操作行云流水一般,现在我们来思考一个问题。假如我从数据库查询出一个List,需要给这个List额外增加一个字段,这个新字段需要从别的表里面查询,该怎么办?

比如,我现在要在类型管理页面增加对应类型的日记数量。

这是类型管理的页面。

SQL调优:让Java内存分担计算_开发语言_03

我们打算加一列,显示文章的总数量。

一个简单的思路就是,先获取类型的列表,然后一次按照类型去查询对应文章的数量。

页面用的是axios异步查询的数据。

getData(){
  var index = layer.load(1); //添加laoding,0-2两种方式
  axios.post('${basePath}/sys-blog-type/selectAll',{}).then(r =>{
    layer.close(index);    //返回数据关闭loading
    if(r.data.code != '0000'){
      layer.msg(r.data.message,{icon:2});
      return;
    }
    console.log(r.data.data);
    this.listData = r.data.data;
  }).catch(error => {
    layer.msg(error.response.status,{icon:2});
    layer.close(index);    //返回数据关闭loading
  })
},

SysBlogTypeController

@RequestMapping("/selectAll")
public List<SysBlogType> selectAll(){
    return sysBlogTypeService.selectAll();
}

SysBlogTypeServiceImpl

@Override
public List<SysBlogType> selectAll() {
    QueryWrapper<SysBlogType> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("user_id", StpUtil.getLoginId());
    return sysBlogTypeMapper.selectList(queryWrapper);
}

代码一目了然,就是结合MybatisPlus做了条件查询。 我们通过controller发现,返回给前端的是List,我们需要增加一列,就需要在这里添加一个字段。

@TableField(exist = false)
private Integer blogNumber;

加上注解@TableField(exist = false)是因为这个字段只是返回给前端用的,不需要和数据库表做绑定。

修改service

@Autowired
BlogMapper blogMapper;

@Override
public List<SysBlogType> selectAll() {
    QueryWrapper<SysBlogType> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("user_id", StpUtil.getLoginId());
    List<SysBlogType> sysBlogTypes = sysBlogTypeMapper.selectList(queryWrapper);
    sysBlogTypes.forEach(e -> {
        Integer typeId = e.getId();
        Integer count = blogMapper.selectCount(new LambdaQueryWrapper<TblSynBlog>()
                .eq(TblSynBlog::getBlogType, typeId));
        e.setBlogNumber(count);
    });
    return sysBlogTypes;
}

这几行代码是遍历博客类型,计算每个类型下的博客数量,并将数量设置到博客类型实体类中的一个blogNumber属性中。

页面代码修改:

SQL调优:让Java内存分担计算_开发语言_04

效果:

SQL调优:让Java内存分担计算_sql_05

目的是达到了,但是假如类型非常多,就会导致for循环耗时过长。所以,我们一般不推荐在for循环里面再去查询数据库的。

优化:我们可以先把博客信息查询出来,然后用内存去计算。

@Override
public List<SysBlogType> selectAll() {
  // 创建查询条件对象
  QueryWrapper<SysBlogType> queryWrapper = new QueryWrapper<>();
  // 设置查询条件:用户ID等于当前登录用户的ID
  queryWrapper.eq("user_id", StpUtil.getLoginId());
  // 查询符合条件的博客分类列表
  List<SysBlogType> sysBlogTypes = sysBlogTypeMapper.selectList(queryWrapper);
  // 获取所有博客分类的ID
  Set<Integer> blogIds = sysBlogTypes.stream().map(SysBlogType::getId).collect(Collectors.toSet());
  // 根据博客分类ID查询对应的博客列表
  List<TblSynBlog> tblSynBlogs = blogMapper.selectList(new LambdaQueryWrapper<TblSynBlog>()
          .in(TblSynBlog::getBlogType, blogIds));
  // 将博客列表按照分类ID进行分组
  Map<String, List<TblSynBlog>> tblSynBlogsMap = tblSynBlogs.stream().collect(Collectors.groupingBy(TblSynBlog::getBlogType));
  // 遍历博客分类列表,设置每个博客分类对应的博客数量
  sysBlogTypes.forEach(e -> {
      List<TblSynBlog> synBlogs = tblSynBlogsMap.get(e.getId() + "");
      if (synBlogs != null) {
          e.setBlogNumber(synBlogs.size());
      } else {
          e.setBlogNumber(0);
      }
  });
  // 返回博客分类列表
  return sysBlogTypes;
}

数据不多的话,看不出啥,但是如果数据很多,性能会有一个显著的提升。

源码下载

这个案例我是在springboot日记本系统里面完成了,有需要源码的小伙伴直接clone这个项目即可。

SQL调优:让Java内存分担计算_数据_06

标签:queryWrapper,Java,mav,List,博客,查询,调优,SQL,id
From: https://blog.51cto.com/u_10957019/6509594

相关文章

  • Java百炼成仙1.1 他叫叶小凡
    第1章陨铁山脉篇1.1他叫叶小凡“这里是哪里?”男子揉了揉有些迷糊的脑袋,环顾四周,只见一望无际的平原。他的白色服饰在强烈的阳光下发出闪亮的光芒,仿佛是一抹清新的色彩点缀在这沉寂的荒野之中。天空中阳光透过透明的大气层倾泻而下,温暖的光线照耀着男子苍白的脸庞。空气中的尘埃让......
  • SQL语句_链表(上)
    说到连表查询,我们先了解下别名。别名可以用在表上,也可以用在表中参数名。即 SELECT"表格别名"."表中参数名""表中参数别名"FROM“表格名” "表格别名" 或 SELECT"表格别名"."表中参数名"AS"表中参数别名"FROM“表格名”AS"表格别名" 举个例子 SELECTSI.st......
  • DataX在Windows上实现Mysql到Mysql同步数据以及配置多个job/多个表同步定时执行bat
    场景DataX-阿里开源离线同步工具在Windows上实现Sqlserver到Mysql全量同步和增量同步:DataX-阿里开源离线同步工具在Windows上实现Sqlserver到Mysql全量同步和增量同步_sqlserver数据同步工具_霸道流DataX-在Windows上实现postgresql同步数据到mysql:DataX-在Windows上实现postgres......
  • Java代码精简之道-10条代码精简方案
    场景一、Java中利用try-with-resource语句JDK7开始新增了对需要关闭资源处理的特殊语法try-with-resource。所有实现Closeable接口的“资源”,均可采用try-with-resource进行简化。例如InputStream,OutputStream,Connection,Statement,ResultSet等接口都实现了,使用try-with-reso......
  • sql server 转移日志文件
    sqlserver转移日志文件要将SQLServer的日志文件转移到不同的位置,你可以按照以下步骤进行操作:1.首先,通过执行以下查询,获取当前数据库的日志文件的逻辑名称(LogicalName):  ```sql  USEYourDatabaseName;  SELECTname,physical_nameFROMsys.master_filesWHEREt......
  • 【mysql】1378. 使用唯一标识码替换员工ID
    题目:Employees表:±--------------±--------+|ColumnName|Type|±--------------±--------+|id|int||name|varchar|±--------------±--------+id是这张表的主键。这张表的每一行分别代表了某公司其中一位员工的名字和ID。EmployeeUNI表:±--------......
  • 必知必会:MySQL
    复制表结构和其数据:createtabletable_name_newasselect*fromtable_name_old表结构相同,复制表数据:insertintotable_name_newselect*fromtable_name_old表结构不同,复制表数据:insertintotable_name_new(column1,column2...)selectcolumn1,column2........
  • Java多线程-Lesson01-线程的创建
    线程创建的三种方式继承Thread类步骤:继承Thread类重写run()方法调用start()开启线程重写run()方法:@Overridepublicvoidrun(){for(inti=0;i<200;i++){System.out.println("run():"+i);}} run()方法里面就是我们多......
  • 必知必会:Java基础
    创建对象有几种方式(1)new创建对象;(2)反射创建对象;(3)采用clone机制;(4)序列化机制。创建反射对象的几种方式(1)类.class:通过 类名.class 创建反射获取对象; 类.class 是静态加载,是JVM编译时就要加载。Class<ClassDemo>oClass=ClassDemo.class;(2) object.getClass() :以 实......
  • java--多态
       ......