为什么后续查询比第一个更快?

时间:2013-07-17 07:28:58

标签: android sqlite

我测量了数据库查询,我发现它第一次运行比所有后续查询慢。我第一次运行下面的代码时得到了11。对于所有后续调用,它始终只有1。它是如何工作的,因此在第一次查询后它会更快?

long time = System.currentTimeMillis();
Cursor cursor = DBHelper.getInstance().getAllContacts();
Logger.log(TAG, "measured time is " + String.valueOf(System.currentTimeMillis() - time));

`getAllContacts()方法是:

(getReadableDatabase().rawQuery("SELECT _id, name, title FROM " + CONTACTS_TABLE_NAME, null));

2 个答案:

答案 0 :(得分:1)

这里可能会有一些效果。

首先,您还要对getReadableDatabase()方法进行计时:如果第一次执行重要工作(比如打开数据库文件!)然后缓存它的作用,那么您将需要大量的开销。那。尝试在定时区域之前单独调用该方法,以便您知道开销不会咬人。

其次,SQLite的工作原理是将SQL编译为内部字节码形式,然后在自己的小虚拟机中执行。编译步骤可能具有非常重要的成本,并且特定于SQL和查询的表。幸运的是,你每次都发送相同的SQL(这是一个常量表名,是吗?),SQLite足够聪明,可以实现编译的LRU缓存,这样如果你运行两次相同的查询,它会更快。 (我不知道缓存的大小;它可能是在你构建SQLite时设置的,有一些合理的默认值。)你可以在理论上通过每次只查询一个不同的表来测试它,但这很愚蠢。关闭与DB的连接也会消除此缓存,但会保证您的性能不佳;你不应该仅衡量事物的起点,因为没有充分的理由你会承担很多额外的费用。

第三,SQLite很可能只在实际需要时读取有关数据库及其表的一些信息,因此,如果这是针对该表的第一个查询,则可能会产生许多额外成本。在计时运行之前,首先尝试对表进行不同的操作 - 否则从不使用 - 查询。 (另外,请注意我在前一段中的警告。)

第四,ORM层可能正在缓存结果,但坦率地说这实际上是不太可能的,因为这很难做到正确(困难的部分是在何时刷新查询结果缓存到期对于正在更新的数据库,实际上更容易不打扰这么复杂。)

答案 1 :(得分:0)

第一次调用SQL语句时,SQLite引擎必须准备该类型化的SQL语句,即在机器可执行代码中转换人类可读的文本,这表示略有开销。