android数据库优化
Android数据库优化
瞎扯
其实自己在BAT的某家工作过,另外2家也都面试过,据我工作和面试的情况感觉各大公司对于客户端数据库的使用是比较少的,尽量的情况都是在内存中做,或者文件。比如新浪微博大部分的可持久化数据是基于文件的而不是数据库不知道是基于什么考量。
但是之前我工作的部门是根据谷歌的开发理念是做了基于以cursor为model,以loader,notify为model和view的双向关联机制,同时基于uri设计rest风格的数据访问,整个这套机制我会在以后的文章中阐述以下, 这里主要还是写写我之前做过的一些数据库优化的情况。
其实瞎扯内容的核心是想说好像大部分的客户端开发其实是不重视数据库的,也没有遵循android的这一套机制的开发,所以可能使用场景有限。
关于三范式
三范式其实讲的是数据的唯一性,不可再fen'chai以及低冗余,但是在现实中因为客户端开发和服务器开发的不同,又或者是因为性能要求的不同我们在数据库设计上并不完全是遵循三范式的。
关于客户端的特殊性
其实数据库设计上来说肯定是服务器的同学设计的更合理性能更好,但是客户端也是有其特殊性的,以下是我觉得的几大特殊情况。
1、数据非持久化
对于客户端来说数据存在数据库并不一定是为了持久化,可能是为了更好的结构化和使用,那么就会存在设计上和服务器不一样的地方,我们可以在下垃操作时将数据清除等操作。
2、更能接受冗余
客户端的数据和服务器一比,那简直就是小巫见大巫,虽然移动设备的性能与服务器的性能相比也是小巫见大巫,但是客户端的开发上我们依然可以接受冗余来换取更快的查询速度。
sqlite简介
sqlite每个数据库都是以单个文件的形式存在,这些数据都是以B-Tree的数据结构形式存储在磁盘上。同时sqlite更改数据的时候默认一条语句就是一个事务,有多少条数据就有多少次磁盘操作。
另外还有一个很重要的就是sqlite的共享锁和独享锁机制,sqlite在可以写数据库之前,它必须先读这个数据库,看它是否已经存在了.为了从数据库文件读取,第一步是获得一个数据库文件的共享锁。一个“共享”锁允许多个数据库联接在同一时刻从这个数据库文件中读取信息。“共享”锁将不允许其他联接针对此数据库进行写操作。
在修改一个数据库之前,SQLite首先得拥有一个针对数据库文件的“Reserved”锁。Reserved锁类似于共享锁,它们都允许其他数据库连接读取信息。单个Reserved 锁能够与其他进程的多个共享锁一起协作。然后一个数据库文件同时只能存在一个Reserved 。因此只能有一个进程在某一时刻尝试去写一个数据库文件。
然后将此锁提升成一个独享锁,一个临界锁允许其他所有已经取得共享锁的进程从数据库文件中继续读取数据。但是它会阻止新的共享锁的生成。也就说,临界锁将会防止因大量连续的读操作而无法获得写入的机会。
所以从sqlite本身的机制看来事务的方式去提交数据,本身是多线程乃至多进程数据安全的,但是android在并发写的时候还是会爆出数据库锁住的异常,我们在开发过程中需要尽量避免。
索引简介
已经有很多文章说了,肯定说的比我好,这里附带一个链接:数据库索引
开发注意事项
基于以上的情况来看,我个人在开发中会分为以下两种情况注意性能的优化。
1、数据库性能上
1.1 批量事务插入,提升数据插入的性能
由于sqlite默认每次插入都是事务,需要对文件进行读写,那么减少事务次数就能简书磁盘读写次数从而获得性能提升。
1.2 单条sql优于多条sql
实测发现,对于几十条sql插入当你替换成单条sql时性能有所提升,但是这里要注意的是,换成单条可读性较差,同时会出现sql超长的错误。
1.3 读和写操作是互斥的,写操作过程中可以休眠让读操作进行
由于第一步所说的多数据事务插入,从而会导致插入时间增长那么也会影响数据展示的速度,所以可以在插入过程中休眠操作,以便给读操作流出时间展示数据。
1.4 使用索引
适当的索引的好处是让读取变快,当然带来的影响就是数据插入修改的时间增加,因为还得维护索引的变化。不过对于大部分的读操作多于写操作的数据库来说索引还是十分有必要的。关于如何设计索引,可以参考下面这个文章:
1.5 使用联合索引
过多的索引同时也会减慢读取的速度,很典型的一个情况就是比如要同时根据省市区县查询,又可以根据年月日查询,如果每个都做索引那么读取速度将会显著降低。
对于这种有层级关系的关键字,就可以考虑联合索引了,比如首先根据省查询,然后根据省市查询,层层递进到省市区县的查询方式,就可以使用联合索引,效果非常好。
1.6 勿使用过多索引
1.7 增加查询条件
当你只要一条数据时增加limit 1,这样搜索到了后面的就不会再查询了,大大的加快了速度
1.8 提前将字段的index映射好
减少getColumnIndex的时间,可以缩短一半的时间
2、数据库设计上
2.1 通过冗余换取查询速度
2.2 减少数据来提升查询速度
比如下拉操作时,先清除旧数据,再插入新数据保证数据库中的数据总量小,提升查询速度。
2.3 避免大数据多表的联合查询
和2.1的方式其实是一样的原理,只是这里需要特别拿出来说明以下,比如有文件表,还有多媒体文件表,你可以设计成一张文件表,一张多媒体关联表存放多媒体数据,文件信息还是在文件表中,然后通过外键关联。
但是如果两个表数据很多,主键还不一致同时数据从服务器下来的数序也不一致那么,两个表的联合查询出来的数据要慢的多,这个时候就可以用冗余来唤起查询速度了。