Java Android:多个SQLLite数据库(每个表一个)会加速并发写入吗?

Java Android:多个SQLLite数据库(每个表一个)会加速并发写入吗?,java,android,multithreading,sqlite,Java,Android,Multithreading,Sqlite,以前已经观察到,如果我们不使用事务,并发写入SQLLite数据库是“缓慢的”(…不确定这如何适用于我们写入SD卡的Android)。这是在没有多个线程写入同一数据库的情况下报告的。我记得读过这样一篇文章:如果使用多个线程写入数据库,那么锁定会更慢(如果我再次找到它,我将添加这篇文章) 现在,我有一个场景,从14个线程写到一个数据库。每次写入大约每秒在同一时间开始,由1到60个条目组成每个线程写入不同的表。这些表是完全独立的,也就是说,我永远不需要进行连接或类似操作。这使得mz场景与其他场景非常不

以前已经观察到,如果我们不使用事务,并发写入SQLLite数据库是“缓慢的”(…不确定这如何适用于我们写入SD卡的Android)。这是在没有多个线程写入同一数据库的情况下报告的。我记得读过这样一篇文章:如果使用多个线程写入数据库,那么锁定会更慢(如果我再次找到它,我将添加这篇文章)

现在,我有一个场景,从14个线程写到一个数据库。每次写入大约每秒在同一时间开始,由1到60个条目组成每个线程写入不同的表。这些表是完全独立的,也就是说,我永远不需要进行连接或类似操作。这使得mz场景与其他场景非常不同,例如

我的问题是,虽然我已经通过缓存条目并使用事务将它们写入数据库进行了优化,但我仍然想知道是否可以通过为每个表创建一个独立的数据库来进一步加快速度。也就是说,线程不应该以这种方式锁定。但我不确定这是否会产生预期的效果,也就是说,完全摆脱锁定


你们中有没有人有这方面的经验,或者可以向我解释为什么或者为什么我的方法不是一个好主意?提前谢谢。

好的,我在我的场景中做了一些实验。结果并不十分清楚,但总的来说,我想说,这两种方法都可以(使用一个数据库或使用单独的数据库)。我注意到的是,对于每个表,有一种轻微的趋势,即单独的数据库在开始时速度较慢,但随着时间的推移,速度会加快,而使用单个数据库在开始时似乎较快,但随着时间的推移,速度会稍慢。在这篇文章中,我将报告我的发现,并接受它作为目前的答案。如果有人有更透彻的解释,可能是用一些理论,而不仅仅是经验证据,我会改变这个观点

详细场景:我正在使用Microsoft Band 2 Android API,对于每个传感器,我使用HandlerThread定义一个侦听器,并将其订阅到传感器管理器(始终使用最大频率)。每个侦听器都获得一个SQLiteOpenHelper,用于获取一个可写数据库“getWriteableDatabase”。在写入数据库之前,快速传感器缓存了60个样本现在,我们可以为每个传感器定义不同的SQLiteOpenHelper,也可以使用相同的SQLiteOpenHelper

由于我们同意使用转换可以使事情更快(我能够确认加速系数为20),因此我在以下实验中使用了事务,即在写入数据库之前缓存60个样本的传感器

实验 在实验中,我计算了每个传感器/线程的几个插入的平均值。我报告用于平均的时间和样本数。格式是

([average insert time in ms] / [number of runs] / [last insert time in ms]  ): [SENSOR]: [number of inserted values]
用于所有线程的单个SQLiteOpenHelper(一个数据库) 运行1 运行2 每个线程使用不同的SQLiteOpenHelpers(每个传感器使用一个数据库) 运行1 运行2
好的,我在我的场景中做了一些实验。结果并不十分清楚,但总的来说,我想说,这两种方法都可以(使用一个数据库或使用单独的数据库)。我注意到的是,对于每个表,有一种轻微的趋势,即单独的数据库在开始时速度较慢,但随着时间的推移,速度会加快,而使用单个数据库在开始时似乎较快,但随着时间的推移,速度会稍慢。在这篇文章中,我将报告我的发现,并接受它作为目前的答案。如果有人有更透彻的解释,可能是用一些理论,而不仅仅是经验证据,我会改变这个观点

详细场景:我正在使用Microsoft Band 2 Android API,对于每个传感器,我使用HandlerThread定义一个侦听器,并将其订阅到传感器管理器(始终使用最大频率)。每个侦听器都获得一个SQLiteOpenHelper,用于获取一个可写数据库“getWriteableDatabase”。在写入数据库之前,快速传感器缓存了60个样本现在,我们可以为每个传感器定义不同的SQLiteOpenHelper,也可以使用相同的SQLiteOpenHelper

由于我们同意使用转换可以使事情更快(我能够确认加速系数为20),因此我在以下实验中使用了事务,即在写入数据库之前缓存60个样本的传感器

实验 在实验中,我计算了每个传感器/线程的几个插入的平均值。我报告用于平均的时间和样本数。格式是

([average insert time in ms] / [number of runs] / [last insert time in ms]  ): [SENSOR]: [number of inserted values]
用于所有线程的单个SQLiteOpenHelper(一个数据库) 运行1 运行2 每个线程使用不同的SQLiteOpenHelpers(每个传感器使用一个数据库) 运行1 运行2
考虑你的DB在电话上,它使用闪存。使用不同的文件意味着重新写入闪存的完全不同的块,这意味着使用多个文件实际上可能会对性能造成更大的影响,而不是使用单个文件,其中对每个表的写入可以合并为对单个闪存块的写入。感谢您的输入!我的想法是一样的,但是SQLLite的锁定机制会阻止来自不同线程的写入被组合,我认为,因为对于每次写入,它都会锁定,直到文件系统确认更新。至少这是我从上面链接的SQLLite常见问题解答中理解它的方式。“你怎么看?”闪存MARCB已经磨损了整平,所以所有新数据最终都会在同一块。考虑到你的DB在电话上,它使用闪存。使用不同的文件意味着重新写入该闪存的完全不同的块,这意味着使用多个文件实际上可能会对性能造成更大的影响,而不是使用单个文件
(88.95454545454545 / 66.0 / 128 ): ACCELEROMETER: 60
(75.109375 / 64.0 / 66 ): GYROSCOPE: 60
(31.906976744186046 / 129.0 / 16 ): AMBIENT_LIGHT: 1
(25.863636363636363 / 66.0 / 15 ): HEART_RATE: 1
(27.237942122186496 / 311.0 / 15 ): GSR: 1
(33.08064516129032 / 62.0 / 8 ): CALORIES: 1
(29.258064516129032 / 62.0 / 10 ): DISTANCE: 1
(39.0655737704918 / 61.0 / 15 ): PEDOMETER: 1
(32.406976744186046 / 86.0 / 11 ): RR_INTERVAL: 1
(32.640625 / 64.0 / 82 ): BAROMETER: 1
(41.292307692307695 / 65.0 / 89 ): ALTIMETER: 1
...
(94.10264385692068 / 643.0 / 61 ): ACCELEROMETER: 60
(77.9188767550702 / 641.0 / 77 ): GYROSCOPE: 60
(33.86671987230646 / 1253.0 / 19 ): AMBIENT_LIGHT: 1
(30.63809523809524 / 630.0 / 33 ): HEART_RATE: 1
(28.691152986266367 / 3131.0 / 12 ): GSR: 1
(32.55810147299509 / 611.0 / 22 ): CALORIES: 1
(31.56774193548387 / 620.0 / 41 ): DISTANCE: 1
(40.27786752827141 / 619.0 / 49 ): PEDOMETER: 1
(31.76108870967742 / 992.0 / 38 ): RR_INTERVAL: 1
(31.466453674121407 / 626.0 / 11 ): BAROMETER: 1
(40.610845295055825 / 627.0 / 19 ): ALTIMETER: 1
(201.98076923076923 / 52.0 / 188 ): ACCELEROMETER: 60
(203.69230769230768 / 52.0 / 72 ): GYROSCOPE: 60
(100.16666666666667 / 102.0 / 37 ): AMBIENT_LIGHT: 1
(125.3    2692307692308 / 52.0 / 47 ): HEART_RATE: 1
(74.4563492063492 / 252.0 / 46 ): GSR: 1
(122.25490196078431 / 51.0 / 13 ): CALORIES: 1
(118.3921568627451 / 51.0 / 34 ): DISTANCE: 1
(127.82352941176471 / 51.0 / 29 ): PEDOMETER: 1
(112.72527472527473 / 91.0 / 34 ): RR_INTERVAL: 1
(106.27450980392157 / 51.0 / 18 ): BAROMETER: 1
(128.2941176470588 / 51.0 / 24 ): ALTIMETER: 1
...
(103.7621776504298 / 698.0 / 71 ): ACCELEROMETER: 60
(99.96418338108883 / 698.0 / 102 ): GYROSCOPE: 60
(27.61911764705882 / 1360.0 / 20 ): AMBIENT_LIGHT: 1
(31.57247437774524 / 683.0 / 37 ): HEART_RATE: 1
(24.713699031974187 / 3409.0 / 13 ): GSR: 1
(31.17921686746988 / 664.0 / 28 ): CALORIES: 1
(34.1037037037037 / 675.0 / 26 ): DISTANCE: 1
(36.275555555555556 / 675.0 / 31 ): PEDOMETER: 1
(30.485689505637467 / 1153.0 / 26 ): RR_INTERVAL: 1
(32.23494860499266 / 681.0 / 10 ): BAROMETER: 1
(36.75917767988253 / 681.0 / 16 ): ALTIMETER: 1
(126.11940298507463 / 67.0 / 77 ): ACCELEROMETER: 60
(128.82539682539684 / 63.0 / 44 ): GYROSCOPE: 60
(58.16153846153846 / 130.0 / 29 ): AMBIENT_LIGHT: 1
(62.53731343283582 / 67.0 / 28 ): HEART_RATE: 1
(50.798701298701296 / 308.0 / 9 ): GSR: 1
(81.62903225806451 / 62.0 / 33 ): CALORIES: 1
(57.45161290322581 / 62.0 / 19 ): DISTANCE: 1
(60.56666666666667 / 60.0 / 14 ): PEDOMETER: 1
(61.56603773584906 / 106.0 / 14 ): RR_INTERVAL: 1
(68.078125 / 64.0 / 23 ): BAROMETER: 1
(80.27272727272727 / 66.0 / 27 ): ALTIMETER: 1
...
(78.23076923076923 / 702.0 / 105 ): ACCELEROMETER: 60
(82.7560975609756 / 697.0 / 56 ): GYROSCOPE: 60
(27.407326007326006 / 1365.0 / 16 ): AMBIENT_LIGHT: 1
(25.03202328966521 / 687.0 / 17 ): HEART_RATE: 1
(22.503373423291286 / 3409.0 / 20 ): GSR: 1
(27.905263157894737 / 665.0 / 10 ): CALORIES: 1
(28.832592592592594 / 675.0 / 13 ): DISTANCE: 1
(30.034175334323923 / 673.0 / 17 ): PEDOMETER: 1
(25.60211267605634 / 1136.0 / 22 ): RR_INTERVAL: 1
(29.501466275659823 / 682.0 / 18 ): BAROMETER: 1
(33.88157894736842 / 684.0 / 23 ): ALTIMETER: 1