Mybatis-SQL分析组件

mybatis,sql,分析,组件 · 浏览次数 : 375

小编点评

**慢sql预警和动态sql替换功能设计** **目的:** * 预警慢sql出现 * 快速解决线上慢sql问题 * 支持动态对线上sql进行替换 **架构:** * 启用慢sql分析功能时,自动触发分析。 * 分析结果用于生成sql优化建议和动态替换配置。 **功能:** **慢sql预警:** * 使用监控工具(如 Prometheus)监控系统指标,包括执行时间、等待时间等。 * 当指标超过阈值时,触发慢sql分析。 **动态sql替换:** * 在慢sql分析完成后,生成sql优化建议和动态替换配置。 * 配置可以用于在线运行,以立即解决问题。 **性能优化:** * 基于性能测试环境,支持定制化配置,决定每个sql是否仅进行一次检查、或者按某个时间间隔进行配置。 * 支持动态对线上sql进行替换,可以对线上问题快速止损。 **扩展:** * 支持评分规则,根据执行结果自动生成优化建议。 * 支持输出方式的自定义扩展,以满足不同需求。 **成本效益:** * 启用慢sql分析功能仅需要配置,无代码侵入。 * 支持动态配置,可根据需求灵活调整性能。 **其他优势:** * 预警慢sql有助于预防线上问题,提高系统稳定性。 * 支持动态sql替换,快速解决线上问题。 * 提供性能优化建议,可以最大限度地避免线上产生慢sql。

正文

背景

大促备战,最大的隐患项之一就是慢sql,带来的破坏性最大,也是日常工作中经常带来整个应用抖动的最大隐患,而且对sql好坏的评估有一定的技术要求,有一些缺乏经验或者因为不够仔细造成一个坏的sql成功走到了线上,等发现的时候要么是造成了线上影响、报警、或者后置的慢sql采集发现,这时候一般无法快速止损,需要修改代码上线、或者调整数据库索引。

核心痛点:

1、无法提前发现慢sql,可能恶化为慢sql的语句

2、线上出现慢sql后,无法快速止损

解决思路

1、把问题解决在上线之前,最好的办法就是在测试阶段,甚至在开发阶段就发现一个sql的好坏

2、线上发现慢sql后除了改代码上线、调整数据库表索引的方式外,支持热更新的方式替换sql语句

部门内部,目前大部分数据库框架采用的mybatis,然后基于mybatis本身的实现机制中,开发一个mybatis组件,可以自动对运行的sql进行提取和分析,定制一套默认的分析规则,让sql在开发环境和测试环境执行的时候,就能够做初步的评估,把有问题的慢sql在这个阶段暴露出来;同时具备sql替换功能,在线上出现问题sql的时候,可以通过ducc配置快速完成对一个sql的在线替换,大大降低线上问题的止损时间。

开源方案调研

目前,主流的sql分析组件,核心功能主要放在了两个方向:1、慢sql的分析和优化建议 2、sql的优化重写功能,而且主要偏运维的辅助功能无法做到无侵入的和应用代码进行集成。也就无法实现我们的核心痛点,慢sql提前分析预警和动态sql替换。

设计方案

核心功能:SQL分析预警能力、SQL替换能力

详细设计

主要分为8个功能模块

模块一:core 主要负责组件的接入到mybatis,以及其它模块的编排调用

模块二:config 主要负责组件配置信息的初始化

模块三:extrat 主要通过解析mybatis 相关对象,提取完整的待执行sql

模块四:analysis 主要拼接分析语句,执行explain分析语句并获取分析结果

模块五:rule sql分析规则的加载和初始化,支持自定义规则

目前默认规则(持续扩展):

1、查询未匹配索引

2、匹配索引过滤效果较差

3、返回行数过多

4、使用了文件排序

模块六:score 基于分析结果和配置的评分规则进行匹配打分,优化建议组装

模块七:out 输出模块,对于输出结果进行输出,目前已error日志、MQ两种输出方式

模块八:replace替换模块,可以对sql语句基于ducc配置进行动态替换

使用方法

1、引入依赖jar包

<dependency>
    <groupId>com.jd.sql.analysis</groupId>
    <artifactId>sql-analysis</artifactId>
    <version>1.2-SNAPSHOT</version>
</dependency>

2、配置组件xml

<configuration>
    <plugins>
        <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >
            <!-- 开启sql分析功能最简配置 -->
            <property name="analysisSwitch" value="true"/>

            <!-- 开启sql替换功能最简配置 -->
            <property name="sqlReplaceModelSwitch" value="true"/>
            <property name="duccAppName" value="workbench-backend"/>
            <property name="duccUri" value="ucc://xxxx@test.ducc.jd.local/v1/namespace/workbench_backend/config/default/profiles/test?longPolling=60000&necessary=false"/>
            <property name="duccMonitorKey" value="refundBugFlag"/>
        </plugin>
    </plugins>
</configuration>

3、核心配置项

属性 用途 是否必填 默认值 备注
analysisSwitch 是否开启分析功能 false
onlyCheckOnce 是否对一个sqlid只分析一次 true
checkInterval 每个sqlid分析间隔 300000毫秒 onlyCheckOnce 为false才生效
exceptSqlIds 需要过滤不分析的sqlid
sqlType 分析的sql类型 默认select、update 支持
scoreRuleLoadClass 评分规则加载器,用于扩展自定义规则
outModel 默认输出方式 默认值:LOG 支持LOG、MQ两种方式
outputClass 评分结果输出类,用于扩展自定义结果输出方式
sqlReplaceModelSwitch sql替换模块是否开启 默认 false
duccAppName ducc配置的应用名称(jdos)
duccUri ducc uri配置
duccMonitorKey sql替换配置文件对应的key

4、默认分析效果展示

1、慢sql分析效果

2、sql动态替换效果

5、实践使用方案

1、慢sql分析-日志输出+关键词告警

<configuration>
    <plugins>
        <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >
            <property name="analysisSwitch" value="true"/>
        </plugin>
    </plugins>
</configuration>

2、慢sql分析-日志输出+mq输出+es存储+Kibana分析

<configuration>
    <plugins>
        <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >
            <property name="appName" value="workbench-backend"/>
            <property name="analysisSwitch" value="true"/>
            <property name="outputModel" value="mq"/>
            <property name="mqApp" value="qlstation"/>
            <property name="mqUser" value="xxx"/>
            <property name="mqPassword" value="xxx"/>
            <property name="mqAddress" value="jmq-testcluster.jd.local:50088"/>
            <property name="mqTopic" value="jdl_kds_key_node_log"/>
        </plugin>
    </plugins>
</configuration>

最终效果

3、慢sql替换-ducc配置动态更新sql语句

<configuration>
    <plugins>
        <plugin interceptor="com.jd.sql.analysis.core.SqlAnalysisAspect" >
            <property name="sqlReplaceModelSwitch" value="true"/>
            <property name="duccAppName" value="workbench-backend"/>
            <property name="duccUri" value="ucc://xxx/v1/namespace/workbench_backend/config/default/profiles/test?longPolling=60000&necessary=false"/>
            <property name="duccMonitorKey" value="sqlReplaceConfig"/>
        </plugin>
    </plugins>
</configuration>

发现慢sql

ducc配置

线上sql被动态替换

注意:功能正式修复后,需去掉该配置,该功能仅供应急处理线上问题,不建议作为功能长期使用

性能测试

测试环境千次普通sql查询,每种场景进行了5次测试

未启用插件耗时:11108ms,10237ms,9482ms,7938ms,8196ms

开启sql分析耗时:16619ms,17333ms,16321ms,19057ms,18164ms

实际配置,只有首次执行或者间隔时间执行,单次影响10ms左右)

开启sql替换耗时:10642ms,8803ms,8353ms,8830ms,9170ms

基本无影响

适用场景

1、慢sql预防

2、线上问题止损

优势

1、核心优势:执行时分析sql,区别于传统的依赖sql执行耗时来评估慢sql,直接基于语法和索引进行前置分析,不仅能预防某些坏sql在上线后发现是慢sql,还能给出sql优化建议,可以大限度的避免线上产生慢sql。支持动态对线上sql进行替换,可以对线上问题快速止损。

2、性能:基于性能和不同的使用场景考虑,支持定制化配置,每个sql是否仅进行一次检查、或者按某个时间间隔进行配置。sql替换几乎无损耗。

3、扩展:基于后续sql评分规则的扩展、以及分析结果以不同的方式输出的考虑,支持评分规则、输出方式的自定义扩展。

4、成本:接入成本低,无代码侵入。

作者:京东物流 扈海涛

来源:京东云开发者社区

与Mybatis-SQL分析组件相似的内容:

Mybatis-SQL分析组件

大促备战,最大的隐患项之一就是慢sql,带来的破坏性最大,也是日常工作中经常带来整个应用抖动的最大隐患,而且对sql好坏的评估有一定的技术要求,有一些缺乏经验或者因为不够仔细造成一个坏的sql成功走到了线上,等发现的时候要么是造成了线上影响、报警、或者后置的慢sql采集发现,这时候一般无法快速止损,需要修改代码上线、或者调整数据库索引。

SpringBoot项目实现日志打印SQL明细(包括SQL语句和参数)几种方式

前言 我们在开发项目的时候,都会连接数据库。有时候遇到问题需要根据我们编写的SQL进行分析,但如果不进行一些开发或者配置的话,这些SQL是不会打印到控制台的,它们默认是隐藏的。下面给大家介绍几种常用的方法。 第一种、代码形式 Mybatis框架是Java程序员最常用的数据库映射框架,MyBatis

MyBatis源码之MyBatis中SQL语句执行过程

本文是MyBatis源码之MyBatis中SQL语句执行过程,使用图文并茂的方式,讲解了SQL语句执行过程,调用了哪些方法,和这些方法是如何调用的。

一文掌握MyBatis的动态SQL使用与原理

摘要:使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。 本文分享自华为云社区《MyBatis详解 - 动态SQL使用与原理》,作者:龙哥手记 。 动态 SQL 是 MyBatis 的强大特性之一。如果你使用

MyBatis实现动态SQL更新

博主记得在一个周五快下班的下午,产品找到我(为什么总感觉周五快下班就来活 😂),跟我说有几个业务列表查询需要加上时间条件过滤数据,这个条件可能会变,不保证以后不修改,这个改动涉及到多个列表查询,于是博主思考了一会想了几种实现方案, 1. 最简单,直接将时间条件写死,由 Service 层传递给 D

Mybatis源码解析之执行SQL语句

作者:郑志杰 mybatis 操作数据库的过程 // 第一步:读取mybatis-config.xml配置文件 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); // 第二步:构建SqlSes

数据库sql中判断时间冲突

数据库现有数据其中两列: s - 开始时间, e - 结束时间. 在新插入数据s', e'之前需要判断两个时间之间是否有重合 因为使用mybatis-plus的缘故, 结论都使用s或e在符号前面. 1. s < e 比如yyyy-MM-dd HH:mm:ss格式的数据, 多用于判断预约时间和每日排班

MyBatis是如何初始化的?

摘要:我们知道MyBatis和数据库的交互有两种方式有Java API和Mapper接口两种,所以MyBatis的初始化必然也有两种;那么MyBatis是如何初始化的呢? 本文分享自华为云社区《MyBatis详解 - 初始化基本过程》,作者:龙哥手记 。 MyBatis初始化的方式及引入 MyBat

MyBatis ORA-01465: 无效的十六进制数字

MyBatis 在插入 Oralce 时报:ORA-01465: 无效的十六进制数字 解决方法: # 插入或更新时 String -> BLOB字段:RAWTOHEX(#{字段名}) String -> DATE:to_date(#{字段名},'yyyy-mm-dd hh24:mi:ss') # 查

把Mybatis Generator生成的代码加上想要的注释

作者:王建乐 1 前言 在日常开发工作中,我们经常用Mybatis Generator根据表结构生成对应的实体类和Mapper文件。但是Mybatis Generator默认生成的代码中,注释并不是我们想要的,所以一般在Generator配置文件中,会设置不自动生成注释。带来的问题就是自动生成代码之