记一次sql查询优化

ops/2024/10/21 6:43:19/

sql_0">记一次sql查询优化

前言
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。

作者:神的孩子都在歌唱

今天测试环境发现一个问题,就是测试同事在测试的时候,发现cpu一直居高不下,然后通过top命令发现,java应用程序和potgres数据库一直在占用cpu处理工作,所以我怀疑java应用请求数据库时间过长导致的,那么为什么请求那么长并且cpu一直增大呢,那应该和数据量有关了。

image-20240919151957003

果不其然,看了一眼数据库,发现有一张表里面有15万条数据,这是一张告警消息和内容的关联表warn_message_content,存储的是告警的消息内容。可是这点数据量也不应该出现这种情况的,然后我去开了一眼代码。

没优化前的sql写法如下

    <select id="query"resultMap="Results">SELECT t.*, (SELECT COUNT(*) FROM warn_message_content WHERE message_id =  #{query.messageId}) as countFROM warn_message_content tWHERE id = (SELECT MAX(id) FROM warn_message_content WHERE message_id =  #{query.messageId});</select>

根据上面sql,我们可以大概知道需求是什么,它是需要根据告警消息的messageId去关联表里面查找总数和最新一条告警内容

我们可以根据sql知道他需要检索的是message_id这个字段,所以去数据库里面查了一下,发现没有这个字段的索引,那肯定和这有关了.

sql">CREATE INDEX idx_warn_message_content_message_id ON warn_message_content(message_id);

通过以上命令添加索引后,查询效率直接升到毫秒

image-20240919160845481

这样问题就解决了。

可是我们可以发现这条sql写的有些问题:

  • 多个子查询:查询中使用了多个子查询。首先是用于获取最大 id 的子查询,然后是用于计算总数的子查询。每次执行时,这些子查询可能会重复扫描 warn_message_content 表,导致性能问题。
  • 效率低:嵌套子查询通常会导致查询性能降低,特别是在数据量很大的情况下。数据库需要执行多个子查询并将结果合并,这会增加计算负担。

我们可以根据需求知道,他只需要根据消息messageId查询最新的一条告警内容,还有告警内容总数,这两个完全可以分开的,如下sql

sql">-- 获取最大 ID
SELECT t.*
FROM warn_message_content t
WHERE message_id = #{query.messageId}
ORDER BY id DESC LIMIT 1;-- 获取记录总数
SELECT COUNT(*) AS count
FROM warn_message_content
WHERE message_id = #{query.messageId};

这样子分开不但能够避免多个子查询,还能够提高代码的可读性。

可是这样子还有个缺点,如果 warn_message_content 表在高频率写入时,没办法保证数据一致性。意思就是如果两个查询在不同的时间点执行,可能会导致 最新的告警内容COUNT(*) 查询结果不一致。解决方法是使用事务,可以确保查询的结果在同一个事务内保持一致。

作者:神的孩子都在歌唱

本人博客:https://blog.csdn.net/weixin_46654114

转载说明:务必注明来源,附带本人博客连接。


http://www.ppmy.cn/ops/118990.html

相关文章

scala 2.12 error: value foreach is not a member of Object

如图所示&#xff1a;在scala 2.11的时候下面的不报错&#xff0c;但是在2.12下报错了 在scala2.12环境下错误如下&#xff1a; 经过查找资料得到&#xff1a;df 后面加上rdd 即可

Power apps:一次提交多项申请

1、添加一个Form&#xff0c;导入sharepoint列表&#xff0c;添加确认&#xff0c;继续&#xff0c;取消按钮 2、在页面的onvisible属性中添加 Set(applynumber,Last(付款申请表).申请编号1); #定义一个申请编号变量&#xff0c;每次申请&#xff0c;就将列表最后一个…

大厂面试真题-Kafka如何保证消息不丢失

详细的回答&#xff1a; Kafka通过一系列精心设计的机制来确保消息不会丢失&#xff0c;这些机制主要包括以下几个方面&#xff1a; 1. 分区与副本机制 分区复制&#xff1a;Kafka中的每个主题&#xff08;Topic&#xff09;被划分为多个分区&#xff08;Partition&#xff…

Element-plus安装及其基础组件使用

简而言之&#xff0c;在main.js中导出以下库,仅此&#xff0c;搞多了出错难排查 import ElementPlus from element-plus //导入ElementPlus 模块 import element-plus/dist/index.css //引入样式 app.use(ElementPlus) //注册库就能使用了 Element Plus 是一个基于 Vue 3 的组件…

算法分析——《二分查找》

&#x1f6e9;《二分查找》 &#x1f3a8;题目描述&#xff1a; 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 示例 …

【c++】gdb调试

参考 https://zhuanlan.zhihu.com/p/173652671gdb 多线程调试https://www.cnblogs.com/binliubiao/p/15387845.html 基本调试命令 命令简写形式说明listl查看源码backtracebt, where打印函数栈信息nextn执行下一行steps一次执行一行&#xff0c;遇到函数会进入finish运行到函…

MyBatis 学习总结

1. MyBatis 简介 MyBatis 是一款优秀的持久层框架&#xff0c;简化了 Java 程序与数据库的交互&#xff0c;通过 SQL 映射将 SQL 语句与 Java 对象关联起来。它基于传统 JDBC 的操作进行了封装&#xff0c;使得开发者无需手动编写复杂的 SQL 操作代码。 MyBatis 的特点包括&a…

【软件工程】模块化思想概述

一、定义 模块化&#xff08;modularization&#xff09;&#xff0c;也称为模组化&#xff0c;是产品设计以及项目管理中被广泛使用的一种设计理念。 模块化是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程&#xff0c;有多种属性&#xff0c;分别反映其内部…