SQL 语句特征识别

线上在执行那么多的 SQL 语句, 如何根据 SQL 的特征进行归类, 方便统计一些执行信息?

0x00 SQL 特征计算方法

来看 SQL 的示例:

SELECT * FROM USERS WHERE id = 1;
select * from users where id = 2;

虽然两个语句返回的结果不一样,但特征都是:

  1. USERS 表中查询所有的字段
  2. 条件是 id = ?

因此, 从特征上说, 上述两个 SQL 是一样的, 不一样的是参数, 当然还有大小写. 因此:

如果我们把 SQL 中的所有的参数替换成 ? 并且将所有的大小写统一, 那么计算 SQL 语句的 md5 值就可以作为 SQL 的唯一特征, 也可以叫做 SQL 的 fingerprint

0x01 SQL 特征实现

技术实现原理也很简单, 简单来讲仅需两步:

  1. 解析 SQL, 获得 AST(抽象语法树)
  2. 通过实现 Vistor, 遍历整个 AST, 统一写法, 遇到参数直接换成 ?

Java 程序员很有福气, 可以直接调用 alibaba 开源的 com.alibaba/druid 库的 com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils#parameterize(sql, dbType) 一句话搞定. 更庆幸的是, 人民的活雷锋 druid 库支持很多种 SQL, Oracle/MySQL/Hive 都不在话下.

0x02 SQL fingerprint 用处

识别了 SQL 的特征, 就可以把可以拿到的 SQL 全部计算特征并根据特征 GROUP BY.

MySQL Slow Query

最直接的使用场景就是把 MySQL 的 slow query log 拿出来计算特征, 这样就知道哪一类的 SQL 是执行瓶颈, 说不定发现一万条 Slow Query 其实是一个呢?

大名鼎鼎的 Percona 开源的 Percona Tookit 中的 pt-query-digest 其实就是这个思路, 推荐使用.

更进一步, 大家不都是把日志扔到 ELK 中吗? 更便捷的方式不就是把 MySQL Slow Query Log 解析后扔进 ELK, 并且添加一个 SQL_fingerprint 字段, 这样定位 Slow query 直接搜索一个 SQL_fingerprint 就可以知道类似的 Slow Query 大概是在什么时间段发生的频次了.

数据分析 SQL 识别

现在大家都嚷嚷大数据, 那么分析师会写很多的 SQL 用于数据查询. 如果你有一个 SQL
特征库:

  • 识别禁止的 SQL 查询(比如非常低效率的 Hive SQL, 保护集群不被低效率的 SQL 查询拖垮)
  • 识别错误的 SQL 查询, 例如一种写法的 SQL 是非常易错的, 可以发现有人执行类似的 SQL 后提醒用户查询错误

0x03 总结

识别了 SQL 的特征, 一定还有其他的应用场景有待挖掘, 祝玩儿的开心.

— EOF —

    原文作者:haitaoyao
    原文地址: https://www.jianshu.com/p/3702196974de
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞