以下是我用于从具有数百万条记录的数据库中获取固定数量记录的查询: -
select * from myTable LIMIT 100 OFFSET 0
我观察到的是,如果偏移量非常高,例如90000,那么查询执行需要更多时间。以下是具有不同偏移量的2个查询之间的时差:
select * from myTable LIMIT 100 OFFSET 0 //Execution Time is less than 1sec
select * from myTable LIMIT 100 OFFSET 95000 //Execution Time is almost 15secs
有人可以建议我如何优化此查询吗?我的意思是,对于我希望从任何OFFSET中检索的任意数量的记录,查询执行时间应该相同且快速。
新增: - 实际情况是我有一个包含>的数据库。超过100万条记录。但由于它是一个嵌入式设备,我不能做“select * from myTable”,然后从查询中获取所有记录。我的设备崩溃了。相反,我所做的是按照上面提到的查询逐批获取记录(批量大小= 100或1000条记录)。但正如我所提到的,随着偏移的增加,它变得缓慢。所以,我的最终目标是我想从数据库中读取所有记录。但由于我不能在一次执行中获取所有记录,我需要一些其他有效的方法来实现这一点。
答案 0 :(得分:4)
通过执行偏移量为95000的查询,将处理所有以前的95000记录。您应该在表上创建一些索引,并使用它来选择记录。
答案 1 :(得分:4)
正如 JvdBerg 所说,索引不在LIMIT / OFFSET中使用。 简单地添加'ORDER BY indexed_field'也无济于事。
为了加快分页,你应该避免使用LIMIT / OFFSET并使用WHERE子句。例如,如果您的主键字段名为“id”并且没有间隙,那么上面的代码可以像这样重写:
SELECT * FROM myTable WHERE id>=0 AND id<100 //very fast!
SELECT * FROM myTable WHERE id>=95000 AND id<95100 //as fast as previous line!
答案 2 :(得分:2)
正如@ user318750所说,如果你知道你有一个连续的索引,你可以简单地使用
select * from Table where index >= %start and index < %(start+size)
然而,这些案件很少见。如果您不想依赖该假设,请使用子查询,例如使用始终为索引的rowid
,
select * from Table where rowid in (
select rowid from Table limit %size offset %start)
这会加快速度,特别是如果你有“胖”行(例如包含blob)。
如果保持记录顺序很重要(通常不是),则需要首先订购索引:
select * from Table where rowid in (
select rowid from Table order by rowid limit %size offset %start)
答案 3 :(得分:1)
使用SQLite,你不需要在一个大的胖数组中一次性返回所有行,你可以为每一行回调。这样,您可以在结果进入时处理结果,这应该解决崩溃和性能问题。
我猜你没有使用C,因为你已经使用了回调,但这种技术应该可以使用任何其他语言。
Javascript示例(来自:https://www.npmjs.com/package/sqlite3)
db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
console.log(row.id + ": " + row.info);
});
答案 4 :(得分:1)
select * from data where rowid = (select rowid from data limit 1 offset 999999);