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

608次阅读
没有评论

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。

完整代码:

解决 Yearning-python 老版本查询慢问题
正文完
 
ddn
版权声明:本站原创文章,由 ddn 2021-08-03发表,共计1408字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。