大型Sqlite数据库搜索
如何高效地在一个有超过90000条记录的大型Sqlite数据库中进行搜索?
我正在使用Python和SQLObject这个工具:
import re
...
def search1():
cr = re.compile(ur'foo')
for item in Item.select():
if cr.search(item.name) or cr.search(item.skim):
print item.name
这个函数运行超过30秒。我该如何让它运行得更快呢?
更新:测试结果:
for item in Item.select():
pass
...所需的时间几乎和我最初的函数一样(从0:00:33.093141到0:00:33.322414)。所以正则表达式并没有消耗太多时间。
一个Sqlite3的命令行查询:
select '' from item where name like '%foo%';
大约只需要一秒钟。因此,主要的时间消耗是因为这个ORM在从数据库中获取数据时效率不高。我猜SQLObject在这里是抓取了整行数据,而Sqlite只接触必要的字段。
6 个回答
0
根据你的例子,结合Reed的回答,你的代码可以像下面这样:
import re
import sqlalchemy.sql.expression as expr
...
def search1():
searchStr = ur'foo'
whereClause = expr.or_(itemsTable.c.nameColumn.contains(searchStr), itemsTable.c.skimColumn.contains(searchStr))
for item in Items.select().where(whereClause):
print item.name
这段代码的意思是:
SELECT * FROM items WHERE name LIKE '%foo%' or skim LIKE '%foo%'
这样做的话,数据库会帮你处理所有的筛选工作,而不是先把90000条记录都取出来,然后再对每条记录进行两次正则表达式的操作。
当然,上面的例子是基于你给的itemsTable和它的列名(nameColumn和skimColumn)来假设的。
2
花30秒来获取90,000行数据可能并不是那么糟糕。
你有没有测试过完成以下操作所需的时间呢?
for item in Item.select():
pass
这样可以看看这个时间是数据库的时间、网络的时间还是应用程序的时间?
如果你的SQLite数据库非常大,那么你可能只是需要进行很多物理读写操作,才能把所有这些数据库内容读取进来。
3
最好的办法是调整你的逻辑,把选择操作放在数据库里,而不是在你的Python程序中。
你应该把Item.select()改成Item.select("""name LIKE ....
这样做的话,确保你的name和skim这两列有索引,就能很快返回结果。90000条记录其实并不算大数据库。