在简单的表上加快SQL查询的5600万条记录

时间:2014-08-12 06:37:43

标签: python mysql sql

我有一个看起来像这样的桌子(SequelPro的快照):

enter image description here

enter image description here

它包含~56M行。它们已被uniprot_idgene_symbol编入索引作为键。 我想要做的是执行以下简单的SQL查询:

SELECT uniprot_id, gene_symbol
FROM id_mapping_uniprotkb

然后将它们存储到Python的字典中。 问题是上面的SQL查询需要很长时间才能完成。 加快速度的方法是什么?

这是我的Python代码:

import MySQLdb as mdb
import MySQLdb.cursors
condb = mdb.connect(host = "db01.foo.com.jp",
                     user = "coolguy",
                     passwd = "xxxx",
                     db = "CISBP_DB",
                     cursorclass = mdb.cursors.SSCursor
                     )
crsr = condb.cursor()
sql = """
          SELECT uniprot_id, gene_symbol
          FROM id_mapping_uniprotkb
          """
crsr.execute(sql)
rows = crsr.fetchall()
#gene_symbol2uniprot = dict(crsr.fetchall())

gene_symbol2uniprot = {}
for uniprotid,gene_symbol in rows:
    gene_symbol2uniprot[gene_symbol] = uniprotid

# do something with gene_symbol2uniprot
# with other process.

2 个答案:

答案 0 :(得分:3)

通过网络传输6500万条记录永远不会很快,特别是如果每​​条记录超过几个字节。数据库不应该增加很多开销,但它没有给你任何价值。

通常我会说你永远不需要做你正在尝试的事情,但我从表名中猜测这与基因组和蛋白质有关,所以它'你可能正在做一些真正需要数据的事情。对问题进行一点澄清将有助于我们更有效地回答。

总之...

数据库旨在过滤和排序海量数据集,直到它们处于可管理的大小。由于您总是获取每条记录,因此您可以更快地将数据以压缩格式存储在磁盘上。除了最小的数据集之外,解压缩的Cpu开销将被从磁盘读取的时间减少所抵消。

如果您暂时停止使用MySql,则应启用protocol compression。这将减少通过线路传输的数据的大小,并且应该以牺牲Cpu为代价来加快速度。这同样适用于compressing the table on disk,但这取决于您的Sql服务器有多强大,它可以容纳多少数据到缓存,访问表的最近时间以及其他一些细节。

更好的解决方案是从数据库中读取记录(例如)100万个记录块,pickle和/或压缩它们并将它们本地写入磁盘(最好是在SSD上)。完成此过程一次后,您可以反序列化本地副本,这应该比使用远程数据库快得多。

编辑:

我想我应该补充一点,如果你不同时需要内存中的所有记录,那么你没有理由不能翻页( SELECT a, b, c FROM x LIMIT 200, 50会为您提供#200-249的记录

答案 1 :(得分:1)

人们经常习惯在核心中加载整个数据库;这使得编码变得非常简单,直到达到您可以轻松适应真实(非虚拟)内存的极限。

只要保持全核心耗尽一些资源,性能就会急剧下降。您真的需要fetchall()还是可以使用for row in cursor:?换句话说,如果你不能选择,减少或以某种方式总结数据库的内容,你就不会对数据进行有用的计算。

(这只是上面各种评论的直接总结。)