我目前正在尝试优化从SQLite数据库中检索日志条目页面的缓慢过程。
我注意到我几乎总是检索下一个条目以及可用条目的数量:
SELECT time, level, type, text FROM Logs
WHERE level IN (%s)
ORDER BY time DESC, id DESC
LIMIT LOG_REQ_LINES OFFSET %d* LOG_REQ_LINES ;
以及可与当前查询匹配的记录总数:
SELECT count(*) FROM Logs WHERE level IN (%s);
(用于显示“m的第n页”)
我想知道,如果我可以连接这两个查询,并在一个sqlite3_exec()中询问它们,只需连接查询字符串即可。那么我的回调函数应该如何呢?我可以通过argc
区分不同类型的数据吗?
您会建议哪些其他优化措施?
答案 0 :(得分:2)
您可以使计数查询返回与选择查询相同的列数,并生成计数查询和选择查询的UNION
。
结果集的第一行将包含总计数。
另一个可能的解决方案在sqlite-users maillist的the post about SQL_CALC_FOUND_ROWS中描述。
关于您的选择查询的一个小注意事项:如果您使用datetime('now')
将记录插入日志表,并且id
是表的自动递增主键,则不需要按时间排序它足以按id DESC
排序。由于自动递增的主键字段是ROWID的别名,因此您将获得显着的性能提升。
顺便说一下,time
是SQLLite中的内置函数,因此您应该使用back-ticks(`)引用列名。
答案 1 :(得分:1)
您可以使用sqlite3_get_table功能查询来收集行 并获取结果行数。
答案 2 :(得分:1)
您可以使用triggers在单独的表中保留每个级别的条目数。插入条目时,触发器需要递增计数,并在删除条目时递减计数。
示例:
create table Log_counts (level primary key, count);
create trigger Log_insert_trigger after insert on Logs
for each row
begin
update Log_counts set count = count + 1 where level = new.level;
end;
create trigger Log_delete_trigger after delete on Logs
for each row
begin
update Log_counts set count = count - 1 where level = old.level;
end;
您需要使用每个级别的计数初始化Log_counts
;在一个空的数据库中,每个级别......
insert into Log_counts (level, count) values (%s, 0);
然后,您不需要对每个显示页面进行计数(*)查询。