当前位置:Gxlcms > mysql > 最近帮人解决一个循环优化的问题

最近帮人解决一个循环优化的问题

时间:2021-07-01 10:21:17 帮助过:45人阅读

这两天接个任务,帮人解决一个循环优化的问题。和开发联系了一下,搞明白原来是这样一个事。因为数据库比较缓慢,这些人决定把数据取到内存里处理。两张10w条左

这两天接个任务,,帮人解决一个循环优化的问题。

和开发联系了一下,搞明白原来是这样一个事。因为数据库比较缓慢,这些人决定把数据取到内存里处理。两张10w条左右的表写了个嵌套循环...


本来听到数据库数据加载内存这一个说法,立刻想到是不是可以加个memcached缓存。但是一看sql,各种复杂的逻辑和多表连接,还是算了。。。

我和他说,你这个思路完全是不正确的。数据库有问题应该explain sql看看到底慢在哪。。。加载内存这种事情应该是vfs层的缓存机制实现的么。如果你想把数据库都加载到内存里处理,不相当于做一个rdbms么,我哪有这能力。

然后我又问他,这些内存里的数据要不要和数据源进行同步?他说,数据取出来用一下,用完就丢。。

好吧。。。看来索引什么的也没意义了。。


最后,只能给了他一个O(m+n)的算法。做了一个demo给他,灰常简单的东西:

#!/usr/bin/env python #coding:utf-8 #简单演示data1和data2的对key的内连接。更多种的表达式解析需要对模式进行重新设计。比如可以再写一个sql解析引擎 #想要实现的sql功能如下: #select * from data1 where data1.value<5 and data2.value like 'a%' and data1.key=data2.key import random #--------------------------------------------- class Data1(object): ''' 第一张表的结构 ''' __slot__=('key','value') def __init__(self,key,value): self.key=key self.value=value def __str__(self): return str((self.key,self.value)) def __repr__(self): return str((self.key,self,value)) class Data2(object): ''' 第二张表的结构 ''' __slot__=('key','value') def __init__(self,key,value): self.key=key self.value=value def __str__(self): return str((self.key,self.value)) def __repr__(self): return str((self.key,self.value)) #------------------------------------------- #where匹配的策略,每个条件变成一个工具类。设计的非常粗糙,只做算法演示用,可以用bool逻辑进行组合 class WhereStratege(object): @staticmethod def judge(data): pass class Little_Then_5(WhereStratege): @staticmethod def judge(data): if data.value<5: return True else: return False class Begin_With_A(WhereStratege): @staticmethod def judge(data): if data.value.startswith('a'): return True else: return False #------------------------------------------------------ #下面是算法的基本逻辑实现。python里面自带hashtable作为其基础数据结构。.net平台基本库也有hashtable的实现。 #在System.Collectons命名空间下面。这些hashtable应该都是带自动扩容的功能。因为我不确定这个实现在大量数据 #下表现怎么样,不过应该是没什么问题的。如果发现在一定量级下hashtable性能出现明显下降。说明这个hashtable的 #碰撞非常严重。很有可能是load factor过高导致的。正常情况下hashtable里面读写数据的时间随着数量增长保持在一个 #稳定的水平。偶尔会出现2、3倍的时间可能是产生了碰撞。每隔一段时间会出现一个比较慢的插入,说明hashtable正在 #进行扩容。扩容的速度随着表的增长会越来越慢,但是每次扩容后距离下一次扩容的时间也越长。因此均摊后的hashtable #的读写性能是O(1)的。 #这个demo里面的result表示结果数组。实际操作中的可能会取两张表的各种字段。随便用一个struct就可以了。因为两张表 #中能够匹配的数据的地址位置已经知道了。可以根据需要生成需要的结构。另外,接口设计也要进行改动。每张表一个匹配 #逻辑的数组。如果你想要同时对多个字段进行连接,如果是与关系,使用一个hashtable就可以了。如果是或关系,需要再 #建立一个hashtable。如果是多表连接,也是同样的道理。 #需要注意的是无论是hash表还是结果缓冲区,都会比较大。需要在堆中生成而不是在线程栈里面。python不太好表现这个。 #另外,hashtable只能用来实现等于的连接条件,无法实现偏序关系,但是我想应该不太会有偏序的,或是更奇怪的连接要求。 def connect_data(data_list1,data_list2,method1,method2): hashtable={} result=[] for data in data_list1: if method1.judge(data): hashtable[data.key]=data for data in data_list2: if data.key not in hashtable: continue elif method2.judge(data): result.append(hashtable[data.key]) return result #--------------------------------------------------------- #只测试了10*10的表,方便验证程序的正确性。由于算法本身很简单,很容易看出是O(m+n)的,demo里就不进行性能测试了。 #第一张表的key和value是随机的10以内的数。第二张表的key是5~14的数,value是abc字母随机的组合。 #本来想把两张表做成生成器,每次迭代的时候自动生成数据来节省内存空间。不过又想了一下,这不符合实际的环境。 def gen_string(length,chartable): ''' 在chartable字符表中随机选择字符生成长度为length的字符串 ''' return ''.join([random.choice(chartable) for i in range(length)]) def test(): ''' 简单的测试用例 ''' keylist1=range(10) keylist2=range(5,15) valuelist1=range(10) valuelist2=[gen_string(3,['a','b','c']) for i in range(10)] random.shuffle(keylist1) random.shuffle(valuelist1) random.shuffle(keylist2) datalist1=map(Data1,keylist1,valuelist1) datalist2=map(Data2,keylist2,valuelist2) print '第一张表的数据:\n' for data in datalist1: print data print '\n第二张表的数据:\n' for data in datalist2: print data print '\n连接以后的数据:\n' r=connect_data(datalist1,datalist2,Little_Then_5,Begin_With_A) for data in r: print data if __name__=='__main__': test()

人气教程排行