`
tnje_2007
  • 浏览: 4659 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

【转】android性能优化-数据库优化

阅读更多
转载自:http://www.trinea.cn/android/database-performance/
1、索引
简单的说,索引就像书本的目录,目录可以快速找到所在页数,数据库中索引可以帮助快速找到数据,而不用全表扫描,合适的索引可以大大提高数据库查询的效率。
(1). 优点
大大加快了数据库检索的速度,包括对单表查询、连表查询、分组查询、排序查询。经常是一到两个数量级的性能提升,且随着数据数量级增长。

(2). 缺点
索引的创建和维护存在消耗,索引会占用物理空间,且随着数据量的增加而增加。
在对数据库进行增删改时需要维护索引,所以会对增删改的性能存在影响。

(3). 分类
a. 直接创建索引和间接创建索引
直接创建: 使用sql语句创建,Android中可以在SQLiteOpenHelper的onCreate或是onUpgrade中直接excuSql创建语句,语句如

1
CREATE INDEX mycolumn_index ON mytable (myclumn)
间接创建: 定义主键约束或者唯一性键约束,可以间接创建索引,主键默认为唯一索引。

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

1
CREATE INDEX mycolumn_index ON mytable (myclumn)
唯一性索引:保证在索引列中的全部数据是唯一的,对聚簇索引和非聚簇索引都可以使用,语句为

1
CREATE UNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn)

c. 单个索引和复合索引
单个索引:索引建立语句中仅包含单个字段,如上面的普通索引和唯一性索引创建示例。
复合索引:又叫组合索引,在索引建立语句中同时包含多个字段,语句如:

1
CREATE INDEX name_index ON username(firstname, lastname)
其中firstname为前导列。

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

1
CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) WITH ALLOW_DUP_ROW
其中WITH ALLOW_DUP_ROW表示允许有重复记录的聚簇索引
非聚簇索引:

1
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、其他针对Sqlite的优化
(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线程,同时也能防止并发带来的异常。
可使用Android提供的AsyncQueryHandler(感谢@内网无法登陆账号 反馈)或类似如下代码完成:

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);
    }
});
分享到:
评论

相关推荐

    Android-Android----数据库框架GreenDao的使用

    **六、性能优化** 1. 使用懒加载(Lazy Loading):对于一对多的关系,GreenDao默认会一次性加载所有关联对象,但可以通过设置`@Load`和`@Lazy`注解来实现延迟加载,提高性能。 2. 利用缓存:GreenDao的`DaoSession...

    Android性能优化.pdf

    【Android性能优化】是Android开发中的重要环节,涵盖了多个关键领域,包括ANR问题解析、crash监控方案、启动速度与执行效率优化、内存优化、耗电优化、网络传输与数据存储优化以及APK大小优化。 **ANR问题解析**是...

    android-database-sqlcipher-v3.5.7 Android安卓数据库加密开源项目

    3. **定期更新**:关注SqlCipher的新版本,及时更新以获取最新的安全修复和性能优化。 总之,SqlCipher为Android开发者提供了一种简单而有效的数据库加密方案,能够在保护用户数据安全的同时,尽可能降低对应用性能...

    免费:Android性能优化视频百度云下载链接.rar

    这个"免费:Android性能优化视频百度云下载链接.rar"的压缩包文件提供了一个学习资源,可能是由一系列视频教程组成,帮助开发者深入理解和掌握Android应用的性能调优技巧。虽然没有直接提供视频内容,但包含的"免费...

    面试Android性能优化

    本专题将深入探讨Android性能优化的关键知识点,帮助开发者提升应用的运行效率和用户体验。 首先,我们要理解Android性能优化的基本原则:减少资源消耗、提高响应速度、降低内存占用以及提升电池续航。在Java编程...

    android-studio-ide-191.5977832-windows.exe

    在性能优化方面,Android Studio 191.5977832可能包含更快的代码分析器,帮助开发者及时发现并修复潜在问题。除此之外,内存和CPU使用率的降低也是提升开发效率的重要因素,这一版本可能对此进行了优化。 对于...

    Android应用性能优化.pdf

    根据提供的文件信息,“Android应用性能优化.pdf”这一文档主要聚焦于Android应用的性能优化方法与实践。虽然部分内容涉及社群推广信息,并未直接提供具体的性能优化技术细节,但我们可以通过标题及描述推断出文档的...

    database-lock.zip_Android 数据库_Android数据库_android_database-lock_安

    在Android平台上,数据库是应用程序存储数据的重要方式,尤其是在处理用户数据、应用状态或者需要持久化信息时。Android原生支持SQLite数据库,这是一个轻量级的关系型数据库,它被设计为嵌入式数据库,可以直接在...

    Android应用性能优化

    ### Android应用性能优化 在移动开发领域,特别是针对Android平台的应用开发过程中,性能优化是确保应用流畅运行、提升用户体验的关键环节。本篇文章将围绕“Android应用性能优化”这一主题,详细探讨Android应用...

    最新版android-support-v4.jar

    保持`android-support-v4.jar`的最新状态至关重要,因为它通常包含了bug修复、性能优化和新的API功能。旧版本的v4库可能会缺乏某些API,导致应用程序出现功能缺失或运行时错误。定期检查并更新此库,可以确保应用...

    Android代码-Android-performance-optimization

    本篇文章将详细讲解Android性能优化的一些核心知识点,并以"Handler产生的内存泄露"作为其中一个实例进行深入探讨。 首先,我们要了解Android性能优化的主要目标:减少资源消耗、提高响应速度和降低功耗。这包括对...

    Android应用性能优化_人民邮电出版社

    Android 应用性能优化 Android 应用性能优化是指通过各种技术和方法来提高 Android 应用程序的运行速度、响应速度和总体性能的过程。这包括优化应用程序的代码、数据库、网络请求、内存管理、图形渲染、缓存机制等...

    android-database-sqlcipher-v3.3.1 sqllite加密so包

    这个版本号"v3.3.1"表明它是SQLCipher的一个特定稳定版,可能包含了性能优化和安全修复。 SQLCipher是一个开源项目,它的核心功能是对SQLite数据库的SQL查询进行加密,这样即使数据库文件被非法获取,没有正确的...

    android-recyclerview-v7-28.0.0

    7. **性能优化** - 使用DiffUtil工具类,它可以自动计算新旧数据集的变化,减少不必要的视图更新,提高性能。 - 使用PagedLibrary配合Room数据库,实现分页加载,避免一次性加载大量数据导致内存消耗过大。 8. **...

    android_mysql-master.zip

    2. 性能优化:批量操作以减少网络请求次数,缓存常用数据以减少网络延迟,及时关闭不再使用的数据库连接以节省资源。 总结,"android_mysql-master"项目提供了一种创新的方式,使得Android开发者可以在移动设备上...

    android-studio-2021.3.1.15-windows 代号“海豚”(Dolphin)

    在性能优化方面,Android Studio Dolphin进行了显著的改进。编译速度的提升是此次更新的一大亮点,尤其对于大型项目来说,减少了等待时间,提高了开发者的生产力。此外,IDE的内存管理也得到了优化,减少了内存占用...

    Android数据库Demo-GreenDaoTest.zip

    对于初学者来说,这是一个极好的学习资源,对于经验丰富的开发者,它可以帮助快速上手并优化数据库操作。总之,掌握GreenDao能够提升Android应用的数据管理效率,让开发者更专注于业务逻辑,而不是底层的数据库操作...

    Android-sqlite-android一个AndroidSQLite支持库

    6. **性能优化**:通过缓存和批处理等方式,优化了数据访问性能,减少了I/O操作,提高了应用的运行效率。 在具体使用`sqlite-android`时,开发者通常需要以下步骤: 1. **添加依赖**:将`sqlite-android`库添加到...

    sqlcipher-for-android-community-v3.2.0

    1. 性能优化:在v3.2.0版本中,SQLCipher进行了性能优化,提高了加密和解密的速度,降低了对设备资源的消耗。 2. 兼容性增强:此版本增强了对不同Android版本的兼容性,包括对较旧设备的支持。 3. 安全性提升:修复...

Global site tag (gtag.js) - Google Analytics