Python和MYSQL性能:将大量SQL查询结果写入文件

时间:2014-08-11 05:52:47

标签: python mysql performance

我有一个文件,其中包含每行的值字典,我使用每个键作为查询来查询mysql数据库。每个查询的结果都放在一个字典中,一旦生成了查询字典的所有值,就会写出该行。

IN > foo bar someotherinfo {1: 'query_val', 2: 'query_val', 3: 'query_val'
OUT > foo bar someotherinfo 1_result 2_result 3_result

整个过程似乎有点慢,因为我每个文件执行大约200,000个mysql查询,每个样本大约有10个文件,总共大约30个样本,所以我希望加快整个过程。

我只是想知道fileIO是否会造成瓶颈。而不是写入line_info(foo,bar,somblah),然后返回每个结果dict,在将它们分批写入文件之前,我会更好地将这些结果分块到内存中吗?

或者这只是一个不得不等待的情况......?

Example Input line and output line
INPUT
 XM_006557349.1  1       -       exon    XM_006557349.1_exon_2   10316   10534   {1: 10509:10534', 2: '10488:10508', 3: '10467:10487', 4: '10446:10466', 5: '10425:10445', 6: '10404:10424', 7: '10383:10403', 8: '10362:10382', 9: '10341:10361', 10: '10316:10340'}
OUTPUT
 XM_006557349.1  1       -       exon    XM_006557349.1_exon_2   10316   105340.7083  0.2945  0.2     0.2931  0.125   0.1154  0.2095  0.5833  0.0569  0.0508


CODE
def array_2_meth(sample,bin_type,type,cur_meth):                                        
        bins_in = open('bin_dicts/'+bin_type,'r')
        meth_out = open('meth_data/'+bin_type+'_'+sample+'_plus_'+type+'_meth.tsv','w')                                                                                           
        for line in bins_in.readlines():
                meth_dict = {}                                                                                                                                                                       
                # build array of data from each line
                array = line.strip('\n').split('\t')                                                                                                                             
                mrna_id = array[0]
                assembly = array[1] 
                strand = array[2]
                bin_dict = ast.literal_eval(array[7]) 
                for bin in bin_dict:
                        coords = bin_dict[bin].split(':')
                        start = int(coords[0]) -1
                        end = int(coords[1]) +1
                        cur_meth.execute('select sum(mc)/sum(h) from allc_'+str(sample)+'_'+str(assembly) + ' where strand = \'' +str(strand) +'\' and class = \''+str(type)+'\' and position between '+str(start)+' and ' +str(end) + ' and h >= 5')
                        for row in cur_meth.fetchall():
                                if str(row[0]) == 'None':
                                         meth_dict[bin] = 'no_cov'
                                else:
                                         meth_dict[bin] = float(row[0])
                 meth_out.write('\t'.join(array[:7]))
                 for k in sorted(meth_dict.keys()):
                        meth_out.write('\t'+str(meth_dict[k]))
                 meth_out.write('\n')
        meth_out.close()  

不确定添加此代码是否会成为一个巨大的帮助,但它应该显示我接近这个的方式..您可以提供的任何建议我在我的方法中犯的错误或如何优化的提示非常感谢!!!

谢谢^ _ ^

1 个答案:

答案 0 :(得分:1)

我认为fileIO不应该花费太长时间,主要的瓶颈可能是您正在进行的查询量。但是从你提供的例子中我看不到那些开始和结束位置的模式,所以我不知道如何减少你正在进行的查询量。

根据你的测试结果,我有一个可能令人惊讶或愚蠢的想法。(我也不知道关于python的shxt所以忽略语法哈哈)

它看到每个查询只返回一个值吗? 也许你可以尝试像

这样的东西
SQL = ''
for bin in bin_dict:
    coords = bin_dict[bin].split(':')
    start = int(coords[0]) -1
    end = int(coords[1]) +1
    SQL += 'select sum(mc)/sum(h) from allc_'+str(sample)+'_'+str(assembly) + ' where strand = \'' +str(strand) +'\' and    class = \''+str(type)+'\' and position between '+str(start)+' and ' +str(end) + ' and h >= 5'
    SQL += 'UNION ALL'
    //somehow remove the last UNION ALL at end of loop

cur_meth.execute(str(SQL))
for row in cur_meth.fetchall():
    //loop through the 10 row array and write to file

核心思想是使用UNION ALL将所有查询加入到1中,因此您只需要执行1个事务而不是示例中显示的10个事务。您还将10 write to file操作减少为1.可能的缺点是UNION ALL可能很慢,但据我所知,只要您保留它就不应该再处理10个单独的查询我的例子中的SQL格式。

第二个明显的方法是多线程。如果您没有使用机器的所有处理能力,您可能会尝试同时启动多个脚本/程序,因为您所做的只是查询数据并且不会修改任何内容。这会导致单个脚本稍微慢一些,但总体上更快,因为它应该减少查询之间的等待时间。