大型Sqlite数据库搜索

2 投票
6 回答
1887 浏览
提问于 2025-04-15 12:17

如何高效地在一个有超过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条记录都取出来,然后再对每条记录进行两次正则表达式的操作。

你可以在这里找到关于.contains()方法的一些信息

还有这个SQLAlchemy SQL表达式语言教程

当然,上面的例子是基于你给的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条记录其实并不算大数据库。

撰写回答