searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

一种提升SQL特征搜索效率的方法

2023-12-06 01:20:02
9
0

1、问题

SQL特征搜索是数据库产品中使用比较频繁的一个技术,在某些产品中的调用频率非常高,参考数据是一个普通SQL可能存在20个以上的关键字,而数据库流量可能达到每秒50万个请求以上。因此提升SQL特征搜索的效率是提升数据库产品质量中非常重要的一项工作,它可以直接降低性能损耗、减少内存占用、减少请求处理时间,提升产品的整体性能。

最简单直接的方案是通过字符串匹配匹配,以特征库作为匹配模版,对SQL的内容进行匹配。可以很直观的看出,这种方法的时间复杂度太高,难以支撑较高的性能需求

基于正则表达式匹配的SQL特征搜索看起来时间复杂度减少了一个指数级别,但是正则表达式的性能问题是众所周知的。

这个方案在其它厂商的数据库审计产品中使用了,不过需求上有所不同,在数据库审计不仅要求特征匹配,而且要求结构匹配。但是即使是这样,该方案仍然不能准确匹配到特征语法,例如其中的注释和字符串等内容,就很难通过正则表达式表示出来。

使用开源工具Druid对SQL进行分词处理,将所得的关键字或者标识符拿到特征库中进行hash对比。可以看到基本上对SQL扫描一遍就可以得到最终的结果,但是过程中产生了数个字符串对象(select、c_first…),当然也会进行相同多次的堆内存分配。

2、解决方案

本方案依据Postgresql语法手工对SQL进行分词处理,然后依据分词的偏移量直接计算对应关键字或者标识符的hash值,然后拿到特征库中进行搜索对比。可以看到同样是对SQL扫描一遍就可以得到最终的结果,但是过程中避免了多次的堆内存分配。

3、优点

经过相同环境下的测试对比,可知本方案在提高SQL特征搜索效率方面产生了较大的提升。而且由于词法分析的环节,准确率显然比正则表达式方式更高(可以处理注释)。下述表格中记录了相同测试条件下各个方案性能的对比:使用样例SQL进行单线程的性能测试。

SELECT c_first, c_middle, c_last, c_street_1, c_street_2, c_city, /* FOR UPDATE */ c_state, c_zip, c_phone, c_since, c_credit, c_credit_lim, c_discount, c_balance FROM bmsql_customer WHERE c_w_id = ? AND c_d_id = ? AND c_id = ? AND c_middle='FOR UPDATE' FOR UPDATE

 

0条评论
0 / 1000
唐****律
20文章数
2粉丝数
唐****律
20 文章 | 2 粉丝
原创

一种提升SQL特征搜索效率的方法

2023-12-06 01:20:02
9
0

1、问题

SQL特征搜索是数据库产品中使用比较频繁的一个技术,在某些产品中的调用频率非常高,参考数据是一个普通SQL可能存在20个以上的关键字,而数据库流量可能达到每秒50万个请求以上。因此提升SQL特征搜索的效率是提升数据库产品质量中非常重要的一项工作,它可以直接降低性能损耗、减少内存占用、减少请求处理时间,提升产品的整体性能。

最简单直接的方案是通过字符串匹配匹配,以特征库作为匹配模版,对SQL的内容进行匹配。可以很直观的看出,这种方法的时间复杂度太高,难以支撑较高的性能需求

基于正则表达式匹配的SQL特征搜索看起来时间复杂度减少了一个指数级别,但是正则表达式的性能问题是众所周知的。

这个方案在其它厂商的数据库审计产品中使用了,不过需求上有所不同,在数据库审计不仅要求特征匹配,而且要求结构匹配。但是即使是这样,该方案仍然不能准确匹配到特征语法,例如其中的注释和字符串等内容,就很难通过正则表达式表示出来。

使用开源工具Druid对SQL进行分词处理,将所得的关键字或者标识符拿到特征库中进行hash对比。可以看到基本上对SQL扫描一遍就可以得到最终的结果,但是过程中产生了数个字符串对象(select、c_first…),当然也会进行相同多次的堆内存分配。

2、解决方案

本方案依据Postgresql语法手工对SQL进行分词处理,然后依据分词的偏移量直接计算对应关键字或者标识符的hash值,然后拿到特征库中进行搜索对比。可以看到同样是对SQL扫描一遍就可以得到最终的结果,但是过程中避免了多次的堆内存分配。

3、优点

经过相同环境下的测试对比,可知本方案在提高SQL特征搜索效率方面产生了较大的提升。而且由于词法分析的环节,准确率显然比正则表达式方式更高(可以处理注释)。下述表格中记录了相同测试条件下各个方案性能的对比:使用样例SQL进行单线程的性能测试。

SELECT c_first, c_middle, c_last, c_street_1, c_street_2, c_city, /* FOR UPDATE */ c_state, c_zip, c_phone, c_since, c_credit, c_credit_lim, c_discount, c_balance FROM bmsql_customer WHERE c_w_id = ? AND c_d_id = ? AND c_id = ? AND c_middle='FOR UPDATE' FOR UPDATE

 

文章来自个人专栏
数据库
8 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0