如何实现高效的大型Sqlite数据库搜索(超过90000个条目)?
我正在使用Python和SQLObject ORM:
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秒。我应该如何让它跑得更快?
UPD :测试:
for item in Item.select():
pass
...几乎与我的初始函数相同(0:00:33.093141到0:00:33.322414)。所以regexps没时间吃。
Sqlite3 shell查询:
select '' from item where name like '%foo%';
运行大约一秒钟。因此,主要的时间消耗发生是由于从数据库中获取的ORM数据效率低下。我猜SQLObject在这里抓取整行,而Sqlite只触及必要的字段。
答案 0 :(得分:3)
最好的方法是重写逻辑,在数据库中而不是在python程序中进行选择。
而不是做Item.select(),你应该重做它来做Item.select(“”“命名LIKE ....
如果你这样做,并确保索引名称和脱脂列,它将很快返回。 90000个条目不是一个大型数据库。
答案 1 :(得分:2)
获取90,000行的30秒可能并不是那么糟糕。
您是否已对执行以下操作所需的时间进行基准测试?
for item in Item.select():
pass
只是看时间是DB时间,网络时间还是申请时间?
如果您的SQLite数据库在物理上非常大,您可能只需要很多物理I / O来读取所有数据库内容。
答案 2 :(得分:0)
如果你真的需要使用正则表达式,那么你无法做任何事情来加速它的发展。
最好的方法是编写一个sqlite函数,在db引擎中执行比较,而不是Python。
您也可以切换到支持SIMILAR的postgresql等db服务器。
http://www.postgresql.org/docs/8.3/static/functions-matching.html
答案 3 :(得分: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记录并对每条记录执行两次正则表达式操作。
You can find some info here on the .contains() method here
以及SQLAlchemy SQL Expression Language Tutorial here。
当然上面的示例假定您的itemsTable及其所拥有的列(nameColumn和skimColumn)的变量名称。
答案 4 :(得分:0)
我肯定会建议Reed将过滤器传递给SQL(尽管忘记了索引部分)。
我不认为只选择指定的字段或所有字段会有所不同(除非你有很多大字段)。我敢打赌,SQLObject创建/实例化80K对象并将它们放入Session / UnitOfWork进行跟踪。这肯定需要一些时间。
此外,如果您的会话中不需要对象,则必须有一种方法可以使用自定义查询创建选择所需的字段,以便不创建Item
个对象,而只创建元组。
答案 5 :(得分:0)
最初通过Python做正则表达式被认为是y_serial,但那 被放弃了有利于SQLite的GLOB(这要快得多)。 GLOB与LIKE类似,只是它的语法更多 常规:*代替%,?而不是_。
有关详细信息,请参阅http://yserial.sourceforge.net/处的尾注。