我的电子表格大约有1.7万行,总计1 GB,需要对其执行各种查询。对Python最熟悉的是,我的第一种方法是将一堆字典组合在一起,以便于我试图进行的查询。例如。如果我需要能够访问具有特定区号和年龄的每个人,我会制作一个areacode_age二维字典。我最终需要相当多的这些,这使我的内存占用量增加(大约10GB),即使我有足够的RAM来支持这一点,但这个过程仍然很慢。
此时,好像我在玩傻逼的游戏。 “这就是关系数据库的用途,对吧?”,我想。我导入了sqlite3并将我的数据导入到内存数据库中。我认为数据库是为了速度而构建的,这将解决我的问题。
事实证明,做“SELECT(a,b,c)FROM foo WHERE date1< = d AND date2> e AND name = f”这样的查询需要0.05秒。为我的1.7米行执行此操作需要24小时的计算时间。对于这个特定的任务,我对词典的hacky方法快了大约3个数量级(在这个例子中,我无法明确地键入date1和date2,所以我得到的每一行都与名称匹配,然后按日期过滤)。
所以,我的问题是,为什么这么慢,我怎么能让它快?什么是Pythonic方法?我一直在考虑的可能性:
感谢。
答案 0 :(得分:4)
sqlite3太慢了,我需要更重量级的东西
首先,sqlite3速度快,有时比MySQL快
其次,你必须使用索引,在(date1,date2,name)中放一个复合索引会使事情显着提升
答案 1 :(得分:2)
但事实证明,做一个像“SELECT(a,b,c)FROM”这样的查询 foo WHERE date1< = d AND date2> e AND name = f“需要0.05秒 对于我的1.7米行,这需要24小时的计算时间。我的hacky 使用字典的方法快了大约3个数量级 这个特殊的任务(在这个例子中,我无法键入date1 和date2显然,所以我得到的每一行都与名字相符 然后按日期过滤。
你真的尝试这个并且观察它需要24小时吗?处理时间不一定与数据大小成正比。
您是否建议您可能需要运行SELECT (a, b, c) FROM foo WHERE date1<=d AND date2>e AND name=f
170万次?您只需运行一次,它将返回与您的查询匹配的整个行子集。
170万行不小,但对于完全在本地计算机内存中的数据库来说肯定不是问题。 (没有慢速磁盘访问;没有慢速网络访问。)
证明在布丁中。这对我来说非常快(大部分时间用于生成大约1000万个随机浮点数。)
import sqlite3, random
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE numbers (a FLOAT, b FLOAT, c FLOAT, d FLOAT, e FLOAT, f FLOAT)");
for _ in xrange(1700000):
data = [ random.random() for _ in xrange(6) ];
conn.execute("INSERT INTO numbers VALUES (?,?,?,?,?,?)", data)
conn.commit()
print "done generating random numbers"
results = conn.execute("SELECT * FROM numbers WHERE a > 0.5 AND b < 0.5")
accumulator = 0
for row in results:
accumulator += row[0]
print ("Sum of column `a` where a > 0.5 and b < 0.5 is %f" % accumulator)
编辑:好的,所以你真的需要运行170万次。
在这种情况下,您可能需要的是索引。引用维基百科:数据库索引:
数据库索引是提高数据速度的数据结构 数据库表上的检索操作,代价是写入速度较慢 并增加了存储空间。可以使用一个或多个创建索引 数据库表的列,提供快速随机的基础 查找和有效访问有序记录。
你会像CREATE INDEX dates_and_name ON foo(date1,date2,name)
这样做,然后(我相信)像往常一样执行其余的SELECT
语句。试试这个,看看它是否加快了速度。
答案 2 :(得分:0)
由于您已经在谈论SQL,最简单的方法是: