解决Yearning-python老版本查询慢问题

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。

完整代码: