原文出处:http://www.trinea.cn/android/database-performance/

1、索引

简单的说,索引就像书本的目录,目录可以快速找到所在页数,数据库中索引可以帮助快速找到数据,而不用全表扫描,合适的索引可以大大提高数据库查询的效率。

优点

大大加快了数据库检索的速度,包括对单表查询、连表查询、分组查询、排序查询。经常是一到两个数量级的性能提升,且随着数据数量级增长。

缺点

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

分类

(1) 直接创建索引和间接创建索引

直接创建: 使用sql语句创建,Android中可以在SQLiteOpenHelper的onCreate或是onUpgrade中直接excuSql创建语句,语句如下

CREATE INDEX mycolumn_index ON mytable (myclumn)

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

(2) 普通索引和唯一性索引

普通索引

CREATE INDEX mycolumn_index ON mytable (myclumn)

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

CREATE UNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn)

(3) 单个索引和复合索引

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

CREATE INDEX name_index ON username(firstname, lastname)

其中firstname为前导列。

(4) 聚簇索引和非聚簇索引(聚集索引,群集索引)

聚簇索引:物理索引,与基表的物理顺序相同,数据值的顺序总是按照顺序排列,语句为:

CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) WITH ALLOW_DUP_ROW

其中WITH ALLOW_DUP_ROW表示允许有重复记录的聚簇索引

非聚簇索引:

CREATE UNCLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn)

索引默认为非聚簇索引

使用场景

在上面讲到了优缺点,那么肯定会对何时使用索引既有点明白又有点糊涂吧,那么下面总结下:

  • 当某字段数据更新频率较低,查询频率较高,经常有范围查询(>, <, =, >=, <=)或order by、group by发生时建议使用索引。并且选择度越大,建索引越有优势,这里选择度指一个字段中唯一值的数量/总的数量。
  • 经常同时存取多列,且每列都含有重复值可考虑建立复合索引

索引使用规则

  • 对于复合索引,把使用最频繁的列做为前导列(索引中第一个字段)。如果查询时前导列不在查询条件中则该复合索引不会被使用
create unique index PK_GRADE_CLASS on student (grade, class)
select * from student where class = 2未使用到索引
select * from dept where grade = 3使用到了索引
  • 避免对索引列进行计算,对where子句列的任何计算如果不能被编译优化,都会导致查询时索引失效
select * from student where tochar(grade)='2'
  • 比较值避免使用NULL
  • 多表查询时要注意是选择合适的表做为内表。连接条件要充份考虑带有索引的表、行数多的表,内外表的选择可由公式:外层表中的匹配行数*内层表中每一次查找的次数确定,乘积最小为最佳方案。实际多表操作在被实际执行前,查询优化器会根据连接条件,列出几组可能的连接方案并从中找出系统开销最小的最佳方案。
  • 查询列与索引列次序一致
  • 用多表连接代替EXISTS子句
  • 把过滤记录数最多的条件放在最前面
  • 善于使用存储过程,它使sql变得更加灵活和高效(Sqlite不支持存储过程)

索引检验

建立了索引,对于某条sql语句是否使用到了索引可以通过执行计划查看是否用到了索引

2、使用事务

使用事务的两大好处是原子提交和更优性能。

原子提交

原则提交意味着同一事务内的所有修改要么都完成要么都不做,如果某个修改失败,会自动回滚使得所有修改不生效。

更优性能

Sqlite默认会为每个插入、更新操作创建一个事务,并且在每次插入、更新后立即提交。

这样如果连续插入100次数据实际是创建事务->执行语句->提交这个过程被重复执行了100次。如果我们显示的创建事务->执行100条语句->提交会使得这个创建事务和提交这个过程只做一次,通过这种一次性事务可以使得性能大幅提升。尤其当数据库位于sd卡时,时间上能节省两个数量级左右。

Sqlte显示使用事务,示例代码如下:

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

其中sqliteOpenHelper.getWritableDatabase()表示得到写表权限。

3、其他针对Sqlite的优化

语句的拼接使用StringBuilder代替String

这个就不多说了,简单的string相加会导致创建多个临时对象消耗性能。StringBuilder的空间预分配性能好得多。如果你对字符串的长度有大致了解,如100字符左右,可以直接new StringBuilder(128)指定初始大小,减少空间不够时的再次分配

查询时返回更少的结果集及更少的字段

查询时只取需要的字段和结果集,更多的结果集会消耗更多的时间及内存,更多的字段会导致更多的内存消耗。

少用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() {@Overridepublic void run() {// db operetions, u can use handler to send message afterdb.insert(yourTableName, null, value);handler.sendEmptyMessage(xx);}
});

SQLite 数据库表字段巧设计

当缓存bean的属性比较多的时候,数据库表的列字段也就比较多,这样操作数据库的时候很繁琐(代码可能需要不停的put)

项目的初期,表字段可能增加,减少,以及修改,这都需要修改表结构,所以缓存的数据就没啥用

解决方法,我们可以把相关的信息json化之后,保存它的jsonString就可以了

db.execSQL("CREATE TABLE" + TABLE_NAME_CINEMA_SIMPLE + "(Id integer primary key autoincrement,"+ "cityId varchar(10)," + "cinemaId varchar(10)," + "cinemaSimpleInfo varchar(400),"//这里就是我们jsonString+ "insertDate varchar(10))");

性能优化之数据库优化相关推荐

  1. Android 性能优化之数据库优化(一)

    Android性能优化系列汇总已完成,包括: Android 性能优化实例 Android 性能优化之数据库优化(一) Android 性能优化之布局优化 (二) Android 性能优化之Java( ...

  2. zabbix mysql优化 my.cnf_zabbix数据库优化之数据库优化(二)

    zabbix数据库优化之数据库优化二 简介 数据库history设置是保存7天.然后如果你没有分区.虽然数据在减少但是表空间不会减少.浪费硬盘空间的同事缓存内的cache部分也没有被释放.分区后可以迁 ...

  3. insert into select 优化_数据库优化总结

    第一部分:SQL语句优化 1.尽量避免使用select *,使用具体的字段代替*,只返回使用到的字段. 2.尽量避免使用in 和not in,会导致数据库引擎放弃索引进行全表扫描. SELECT * ...

  4. 物联网 mysql数据库优化_MySQL数据库优化大全方法汇总-阿里云开发者社区

    随着数据和负载增加,MySQL数据库会日渐缓慢,性能越来越差,用户体验也随之变差,所以数据库性能优化十分紧迫,云吞铺子分享MySQL数据库优化大全: MySQL数据库优化 云吞铺子先模拟一下数据库访问 ...

  5. table 条数过大优化_MySQL 数据库优化,看这篇就够了 | 不长不短,2000 字小结

    前言 数据库优化一方面是找出系统的瓶颈,提高MySQL数据库的整体性能,而另一方面需要合理的结构设计和参数调整,以提高用户的相应速度,同时还要尽可能的节约系统资源,以便让系统提供更大的负荷. 1. 优 ...

  6. mysql悲观锁优化_MySQL数据库优化(三)—MySQL悲观锁和乐观锁(并发控制)

    一.悲观锁 1.排它锁,当事务在操作数据时把这部分数据进行锁定,直到操作完毕后再解锁,其他事务操作才可操作该部分数据.这将防止其他进程读取或修改表中的数据. 2.实现:大多数情况下依靠数据库的锁机制实 ...

  7. oracle的优化适用于mysql吗_性能优化之数据库优化,适用于Sqlite、Mysql、Oracle、Sql server,详细介绍了索引和事务及部分针对Sqlite的优化...

    本文为性能优化的第一篇--数据库性能优化,原理适用于大部分数据库包括Sqlite.Mysql.Oracle.Sql server,详细介绍了索引(优缺点.分类.场景.规则)和事务,最后介绍了部分单独针 ...

  8. 高级mysql数据库优化_MySQL数据库优化建议

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在WHERE及ORDER BY涉及的列上建立索引. 缺省情况下建立的索引是非群集索引,但有时它并不是最佳的.在非群集索引下,数据在物理上随机存放在数据 ...

  9. mysql数据库服务器优化_MySQL数据库优化经验详谈(服务器普通配置)

    安装好mysql后,配制文件应该在/usr/local/mysql/share/mysql目录中,配制文件有几个,有my- huge.cnf my-medium.cnf my-large.cnf my ...

最新文章

  1. 简单介绍Fedora 8飞信安装及解压
  2. SQLServer过期的解决方案
  3. 向上弹出菜单jQuery插件
  4. 【升级包】jeecg_online 支持主子表列表展示风格模板升级包,简易升级
  5. zabbix利用mutt和msmtp配置邮件报警
  6. 【oracle11g,17】存储结构: 段的类型,数据块(行连接、行迁移,块头),段的管理方式,高水位线...
  7. Chrome 内存和CPU消耗量双料冠军
  8. UVA10934 Dropping water balloons【DP】
  9. 基于阿里云的系统灾备方法架构与安全应急预案介绍
  10. vueminder ultimate 2020中文版(电脑桌面日历工具) v2020.07
  11. mysql schemata_SCHEMATA · xiaoboluo768/mysql-system-schema Wiki · GitHub
  12. 在yandex投放广告的话,需要注册俄罗斯常用的域名吗?
  13. Swift Archiving序列化
  14. 剑指Offer面试题22(Java版):栈的压入、弹出序列
  15. k8s中Pod域名解析失败
  16. 新的、老的、无所不在的毒素
  17. Activiti 学习笔记八:排他网关(ExclusiveGateWay)
  18. 曾国藩《挺经》卷十七藏锋
  19. 【2020 ACM Fellow 华人学者】 陶宇飞 香港中文大学
  20. 电脑文件数据恢复有哪些方法?电脑怎么恢复已删除的文件数据?

热门文章

  1. TikTok电商去年赚了60亿?短视频的尽头是带货?
  2. CPU100%不限性能和100%独享资源的区别
  3. 云给数据中心带来了什么特性?
  4. IOC的理解,整合AOP,解耦对Service层和Dal层的依赖
  5. springboot入门_打包部署
  6. 洛谷 P1851 好朋友
  7. js数组循环删除元素或对象
  8. VIJOS国庆节模拟赛之繁星春水
  9. *62.分页和分段的区别
  10. *36.操作系统中磁盘的调度算法