3

我正在测量打开和关闭数据库以及在其上执行查询和插入的方法的执行时间。对于这四个操作中的每一个,我基本上都会得到执行相关语句之前和之后的时间,如下所示:

for(int i = 0; i < 500; i++) {
    startTime = System.nanoTime();
    long insertResult = db.insert(tableName, null, contentValues);
    endTime = System.nanoTime();
    if(insertResult > -1) {
        generateNoteOnSD(fileName, (endTime - startTime));
    }
}

在插入的情况下:

  • 示例中的最短执行时间为 13 ms(毫秒)
  • 示例中的最大执行时间为 537 ms
  • 超过 50% 的结果集(来自 500 的 259 次“插入”执行)在 15 到 20 毫秒之间。
  • 高于 20 ms 的值具有非常低的频率(1、2 或 3)。

有人可以给我一个关于系统如何执行此类操作的想法/方向吗?我真的不知道持久存储的写入操作是如何完成的,以及它取决于哪些因素。我想知道这一点以试图解释上述测量(为什么同一操作的执行时间会发生变化)。

非常感谢任何帮助。

奥克塔维奥

4

1 回答 1

2

我将假设这是一个常规表,而不是临时表。

让我们从这里最大的性能猪开始。

默认情况下,每个这样的插入都会开始和结束一个新事务。如果您想大大加快速度,请申请

db.beginTransaction();

在你的循环之前,和

db.setTransactionSuccessful();
db.endTransaction;

循环之后。这会将所有插入放在同一个事务中。一定要测量db.endTransaction一些总花费的时间将移动的时间。当您没有手动调用这些操作时,每个操作db.insert都隐含地包含在这些操作中,这称为隐式事务

虽然交易协议本身很复杂,并且会造成一些性能差异,但细粒度的交易会导致硬件速度的差异。事务需要是持久的,因此它们需要写入闪存(写入甚至比读取还要慢,并且每个事务需要多次写入)。相比之下,“一个长事务”写入易失性内存,即使在提交期间数据也需要进入闪存,您只需要写入的一小部分。如果您的行很窄,这种效果会更明显,因为更多的行将适合闪存块并一次写入。

就读取而言,事务在这里的作用较小。这很容易。如果您的应用程序在易失性 RAM 中很热,则所有数据都从那里传输。如果不是,则数据来自闪存。

您的数据激增很可能是由于与数据库竞争的无关后台进程。只有当这些应用程序进行密集计算时才会发生这种情况。如果其中一些进程访问同一个数据库,您也可能会遇到锁争用;即使这些进程正在等待其他东西,这也是可能的。这也可以解释为什么它们的分布如此不规则。这不是唯一的可能性。

对于 SQLite 中使用的算法的一般概述,查看这本书可能很有用,尽管它是为竞争操作系统编写的。

于 2012-07-16T22:34:33.790 回答