安卓开发详解—Android数据库优化

1、索引

简单易行的说,索引就如书本的目录,目录可以迅速找到所在页数,数据库中索引好扶持快速找到数据,而未用全表扫描,合适的目录可以大大提高数据库查询的效率。

(1). 优点

大大加速了数据库检索的快慢,包括针对单表查询、连表查询、分组查询、排序查询。经常是如出一辙到个别只数据级的属性提升,且随着数据数量级增长。

(2). 缺点

目录的创造同掩护有消耗,索引会占用物理空间,且随着数据量的充实而多。
每当对数据库进行增删改时需要保护索引,所以会对增删改之习性是影响。

(3). 分类

a. 直接开立索引和间接创建索引
直白开立:
使用sql语句创建,Android中得以在SQLiteOpenHelper的onCreate或是onUpgrade中直接excuSql创建语句,语句如果

CREATE INDEX mycolumn_index ON mytable (myclumn) 

间接创建:
定义主键约束或唯一性键约束,可以间接创建索引,主键默认为唯一索引。

b. 普通索引和唯一性索引
常见索引:

CREATE INDEX mycolumn_index ON mytable (myclumn) 

唯一性索引:保证在索引列中的浑数码是唯一的,对聚簇索引和非聚簇索引都可使用,语句为

CREATE UNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn) 

c. 单个索引和复合索引

单个索引:索引建立报告句被独包含单个字段,如上面的日常索引和唯一性索引创建示范。

复合索引:又受成索引,在目建立报告句子被同时富含多独字段,语句如果:

CREATE INDEX name_index ON username(firstname, lastname)

其中firstname为前导列。

d. 聚簇索引和非聚簇索引(聚集索引,群集索引)
聚簇索引:物理索引,与基表的情理顺序相同,数据值的依次总是以顺序排列,语句为:

CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) WITH ALLOW_DUP_ROW 

其中WITH ALLOW_DUP_ROW表示同意发生重复记录的聚簇索引

非聚簇索引:

CREATE UNCLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) 

找引默认为非聚簇索引

(4). 使用状况

在面说到了利害,那么必然会针对何时使用索引既来硌清楚又有点混乱吧,那么下总结下:

a. 当有字段数据更新频率比较逊色,查询频率比较高,经常发出限定查询(>, <, =,
>=, <=)或order by、group
by发生时建议以索引。并且选择度更怪,建索引越出优势,这里选择度依一个字段中绝无仅有值的多少/总的多寡。

b. 经常还要存取多排,且各列都包含更值可考虑建复合索引

(5). 索引使用规则

a.
对于复合索引,把以最累的排列做为前导列(索引中第一个字段)。如果查询时前面导列不以询问条件中虽该复合索引不见面让下。

create unique index PK_GRADE_CLASS on student (grade, class) 

select * from student where class = 2未使用到索引 
select * from dept where grade = 3使用到了索引

b.
避免对索引列进行计算,对where子句列的其它计算而无能够为编译优化,都见面促成查询时索引失效

select * from student where tochar(grade)=’2′ 

c. 比较值避免采取NULL

d.
多表查询时若注意是择合适的表做为内表。连接条件一旦充份考虑富含索引的表明、行数多之申,内外表的挑选而由于公式:外层表中的相当行数*内层表中各个一样不成搜索的次数确定,乘积最小为最佳方案。实际多表操作以受实际施行前,查询优化器会根据连年条件,列有几乎组或者的连续方案并从中寻找来体系开发最小之顶尖方案。

e. 查询列与索引列次序一致

f. 用几近表连接代替EXISTS子句

g. 把过滤记录数最多之准放在最前方

h. 善于运用存储过程,它如果sql变得尤其灵活和迅速(Sqlite不支持存储过程)

(6)索引检验

建立了目录,对于有条sql语句是否以到了目录可以由此推行计划查看是否采取了目录。

2、使用工作

用工作的片万分利益是原子提交和再美性能。

(1) 原子提交

法提交代表同一业务内之有修改或都形成或者都非做,如果有修改失败,会自动回滚使得所有修改不见效。

(2) 更美妙性能

Sqlite默认会为每个插入、更新操作创建一个政工,并且以历次插入、更新后就付给。

诸如此类要连续插入100破数据实际上是创建工作->执行语句->提交者进程为还执行了100潮。如果我们来得的创造工作->执行100长告词->提交会教这创造工作以及付出者历程只有开相同不善,通过这种一次性事务可以使性能大幅升级。尤其当数据库位于sd卡时,时间及可知节约两个数据层左右。

Sqlte显示采用工作,示例代码如下:

public void insertWithOneTransaction() { 
    SQLiteDatabase db = sqliteOpenHelper.getWritableDatabase(); // Begins a transaction  db.beginTransaction(); 
try { // your sqls for (int i = 0; i < 100; i++) { 
            db.insert(yourTableName, null, value); 
        } // marks the current transaction as successful  db.setTransactionSuccessful(); 
    } catch (Exception e) { // process it  e.printStackTrace(); 
    } finally { // end a transaction  db.endTransaction(); 
    } 
} 

里面sqliteOpenHelper.getWritableDatabase()表示收获写表权限。

3、其他优化

(1) 语句的拼接使用StringBuilder代替String

其一就算不多说了,简单的string相加会导致创建多独临时对象吃性能。StringBuilder的长空预分配性能好得差不多。如果您对字符串的长有大概了解,如100许符左右,可以一直new
StringBuilder(128)指定初始大小,减少空间不够时之又分配。

(2) 读写表

在写表时调用sqliteOpenHelper..getWritableDatabase(),在读表时候调用sqliteOpenHelper..getReadableDatabase(),getReadableDatabase性能更不错。

(3) 查询时返回重新不见之结果集和重新少之字段。

询问时只有抱需要的字段和结果集,更多之结果会消耗又多的光阴和内存,更多之字段会招致更多的内存消耗。

(4) 少用cursor.getColumnIndex

根据性调优过程中之观察cursor.getColumnIndex的岁月消耗与cursor.getInt相差无几。可以当建表的时用static变量记住某列的index,直接调用相应index而未是每次查询。

public static final String       HTTP_RESPONSE_TABLE_ID = android.provider.BaseColumns._ID;
public static final String       HTTP_RESPONSE_TABLE_RESPONSE = "response"; public List<Object> getData() { 
    …… 
    cursor.getString(cursor.getColumnIndex(HTTP_RESPONSE_TABLE_RESPONSE)); 
    …… 
} 

优化为

public static final String HTTP_RESPONSE_TABLE_ID = android.provider.BaseColumns._ID;  public static final String HTTP_RESPONSE_TABLE_RESPONSE  = "response";  public static final int HTTP_RESPONSE_TABLE_ID_INDEX  = 0;  public static final int HTTP_RESPONSE_TABLE_URL_INDEX = 1;  public List<Object> getData() {     ……     cursor.getString(HTTP_RESPONSE_TABLE_RESPONSE_INDEX);     …… }

4、异步线程

Sqlite是常用于嵌入式开发中之关联项目数据库,完全开源。
同Web常因此的数据库Mysql、Oracle db、sql
server不同,Sqlite是一个内嵌式的数据库,数据库服务器即在你的先后中,无需网络布局与管理,数据库服务器端和客户端运行于平等进程内,减少了网访问的吃,简化了数据库管理。不过Sqlite在起、数据库大小、网络方面存在局限性,并且也表级锁,所以呢没必要多线程操作。

Android中数未多时表查询可能耗时不多,不见面招致anr,不过超过100ms时一致会被用户觉得到延时和卡顿,可以放在线程中运作,但sqlite在出现方面有局限,多线程控制比较辛苦,这时候可运用单线程池,在任务中实行db操作,通过handler返回结果及ui线程交互,既不见面影响UI线程,同时为能够防备出现带来的好。实例代码如下:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); singleThreadExecutor.execute(new Runnable() {       @Override public void run() {  // db operetions, u can use handler to send message after db.insert(yourTableName, null, value);          handler.sendEmptyMessage(xx);     } });
网站地图xml地图