使用select检索SQLite数据耗时过长。

我已经为我的Corona/Lua应用程序使用SQLite创建了一个哈希表,其中包含约70万个值。该表有两列,分别是哈希码(字符串)和值(另一个字符串)。在程序执行期间,我需要多次提供哈希码来获取数据。

我使用如下代码来获取数据:

for p in db:nrows([[SELECT * FROM test WHERE id=']].."hashcode"..[[';]]) do
    print(p)
    -- p = returned value --
end

但这个语句执行起来太慢了。

谢谢,

编辑:

成功了!错误在于主键设置。我将哈希码设置为主键,如下所示,检索时间恢复正常:

CREATE TABLE IF NOT EXISTS test (id STRING PRIMARY KEY , array);

我还像你说的那样提前准备了语句:

stmt = db:prepare("SELECT * FROM test WHERE id = ?;")
[...]
stmt:bind(1,s)
for p in stmt:nrows() do

唯一的问题是数据库文件大小,它从18 MB增加到了29.5 MB。

点赞
用户2864740
用户2864740

确保在 id/哈希码列上有一个 _index_?如果没有,这样的查询将会_非常慢_。这个索引应该是唯一的。

如果只选择值/哈希码 (SELECT value FROM ..),可能有利于在 (id, value)上使用 _covering index_,因为它可以避免额外的寻找行数据(参见 SQLite Query Planning)。尝试使用和不使用这样的 _covering index_。

此外,如果多次查询相同的哈希码,可能值得使用 _caching_。

2013-10-24 20:21:40
用户33252
用户33252

你应该创建一个带有id作为唯一主键的表,这将自动创建一个索引。

create table if not exists test
(
    id text primary key,
    val text
);

你不应该使用字符串连接来构造语句;这是一个安全问题,所以要避免养成这种习惯。此外,你应该在程序初始化时提前准备好语句,并运行准备好的语句。

例如,首先执行以下操作:

hashcode_query_stmt = db:prepare(“SELECT * FROM test WHERE id =?;”)

然后对于每个使用:

hashcode_query_stmt:bind_values(hashcode)
for p in hashcode_query_stmt:urows() do ... end
2013-10-24 21:37:37
用户2545784
用户2545784

如先前所述,确保在ID上有一个索引。

如果现在不能更改表结构,可以临时添加索引:

CREATE INDEX test_id ON test (id);

关于哈希:如果您正在计算哈希以加快搜索速度,请勿这样做!

SQLite将使用您提供的哈希作为任何常规字符串/二进制大对象。此外,关系型数据库管理系统已经针对高效搜索进行了优化,这可以通过索引大大提高。

除非您为节省空间而进行哈希处理,否则在应用程序中计算哈希是浪费处理器时间的。

2013-10-25 08:05:49