2010-04-23 156 views
3

我目前正在试图优化从SQLite数据库检索日志条目页面低迷的过程。在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); 

(用于显示“页面n的m“)

我想知道,如果我可以连接两个查询,并要求他们在一个sqlite3_exec()简单地连接查询字符串。我的回调函数应该如何看待?我可以通过argc区分不同类型的数据吗?

,你有什么建议其他优化?

回答

2

您可以使计数查询返回与选择查询相同的列数,并使计数查询和选择之一成为UNION

结果集的第一行包含总计数即可。

另一种可能的解决方案是在从the post about SQL_CALC_FOUND_ROWS源码用户邮件列表说明。

以及您选择查询一个小提示:如果你插入记录到日志表datetime('now'),并id是表的自动递增的主键,然后按时间排序不是必需的,这是不够的id DESC排序。由于自动递增的主键字段是一个别名ROWID,你会得到一个显著的性能提升。

顺便说一句,time是SQLLite中的一个内置函数,所以你应该用引号(`)引用列名。

+0

实际上,由于DST变化和时钟调整,首先认为按时间排序是必要的。然后它被认为是适得其反的(将DST改变之前和之后的原木混合在一起)并且随后被报废。 – 2011-09-15 15:16:30

1

您可以使用您的查询与sqlite3_get_table函数收集行
并获取结果行数。

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); 

这样你就不会需要一个COUNT(*)查询显示的每一页。