共计 1408 个字符,预计需要花费 4 分钟才能阅读完成。
yearning 是一个开源的 SQL 审核平台,现在版本为 Golang 开源版本,早期版本为 python django 开发的,存在一些小问题,我们是 2019 年使用的,一直感觉查询数据量大的时候特别慢,最近调试发现了初期版本搜索存在的严重 bug,会导致查询异常缓慢,如果你是采用的最新 golang 或最新 python 版本的 yearning,则不需要关注这个问题了。
查询慢问题:
问题代码位置 src/core/api/serachsql.py
主要问题就是下面这段代码,data_set 为查询出来的数据集合,for 循环检查每一个数据字典,然后循环每一个数据字典的 key 和 value,key 也就是 mysql 中的字段,value 也就是 mysql 中的数据,if 判断,如果 value 是 bytes 类型,就把这个 value 更新为 ’blob 字段为不可呈现类型 ’。
# 敏感检查
if critical:
as_list = search.sql_as_ex(sql, custom_com['sensitive_list'])
for l in data_set['data']:
for k, v in l.items():
for n in range(data_set['len']):
if isinstance(v, bytes):
data_set['data'][n].update({k: 'blob 字段为不可呈现类型'})
for i in as_list:
if k == i:
data_set['data'][n].update({k: '********'})
else:
for l in data_set['data']:
for k, v in l.items():
for n in range(data_set['len']):
if isinstance(v, bytes):
data_set['data'][n].update({k: 'blob 字段为不可呈现类型'})
# 查询记录写入 sql
问题就在于上面这步里面多了一个 for 循环
for n in range(data_set['len']):
data_set[‘len’] 为数据条数,如果语句为 select * from xxx limit 3000; 那么 for 循环就是 for n in range(3000),循环次数就是 3000 * 3000,到这里也就知道为什么慢了,接下来就是优化了。
优化的方法也很简单,如果你后台没有设置脱敏字段,就直接更改下面的 else 判断就行。
for index,l in enumerate(data_set['data']):
for k, v in l.items():
if isinstance(v, bytes):
data_set['data'][index].update({k: 'blob 字段为不可呈现类型'})
去除 for 循环,直接根据索引下标更新字段值
你也可以更改为 github 上最新的官方代码
if data_set['data']:
fe = []
for k, v in data_set['data'][0].items():
if isinstance(v, bytes):
fe.append(k)
if len(fe) != 0:
for l in data_set['data']: # O(N^n)
for i in fe:
l[i] = 'blob 字段为不可呈现类型'
两个代码测试速度差异不大,建议更改为 github 上官方的代码,更新之后查询速度会提升很大,原先 16s 的查询,现在只需要 1.5s。
完整代码: