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

性能优化专题已完成五部分:

性能优化实例

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显示使用事务,示例代码如下:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

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而不是每次查询。

Java

1

2

3

4

5

6

7

public static final String       HTTP_RESPONSE_TABLE_ID                  = android.provider.BaseColumns._ID;

public static final String       HTTP_RESPONSE_TABLE_RESPONSE            = "response";

public List getData() {

……

cursor.getString(cursor.getColumnIndex(HTTP_RESPONSE_TABLE_RESPONSE));

……

}

优化为

Java

1

2

3

4

5

6

7

8

9

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 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线程,同时也能防止并发带来的异常。实例代码如下:

Java

1

2

3

4

5

6

7

8

9

10

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);

}

});

Posted@2013-08-10 08:50:18, Filed under Android, Java, 性能优化 by Trinea

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

  1. l源码安装mysql升级_[Linux]javaEE篇:源码安装mysql

    javaEE :源码安装mysql 安装环境 系统平台:CentOS-7-x86_64 数据库版本:mysql-5.6.14 源码安装mysql步骤: 一.卸载mysql 安装mysql之前,先确保l ...

  2. mysql sql归类_带有归类SQL强制转换SQL Server归类介绍

    mysql sql归类 SQL Server collation refers to a set of character and character encoding rules, and infl ...

  3. sql2008能否打开mysql数据库_mysql数据库数据能不能导入到sql server中

    点"测试"按钮确认你的链接是正确的. Press the "Test" button to ensure your connection settings ar ...

  4. #数据库--第1章 Windows 下的数据库导入 TPCH 数据(以 SQL Server 作为示例,MySQL同样适用)

    #数据库--第1章 Windows 下的数据库导入 TPCH 数据(以 SQL Server 作为示例,MySQL同样适用 一.TPCH 简介 二.TPCH 文件 三.生成 TPCH 数据 四.导入 ...

  5. 用于打开和创建SQLite,Microsoft SQL Server,PostgreSQL和MySQL SQL数据库的WPF对话框

    目录 介绍 创建数据库对话框 打开数据库对话框 背景 使用代码 显示数据库对话框 加密 序列化 构建演示应用程序 遗漏 从Github下载源代码 介绍 本文介绍了一些用于创建和打开SQL数据库的便捷对 ...

  6. mysql数据和性能平衡点_MySQL数据库性能优化(2)

    4.影响SQL性能的要素 MySQL数据库的性能不止受到性能参数和底层硬件条件的影响,在这两个条件一定的情况下,开发人员对SQL语句的优化能力更能影响MySQL数据库的性能.由于MySQL中不同数据库 ...

  7. elementui带输入建议查询_知道Profiler是什么吗?带你了解SQL Server的性能优化工具...

    SQL Server Profiler是什么 SQL Server Profiler是一个界面,用于创建和管理跟踪并分析和重播跟踪结果. 这些事件保存在一个跟踪文件中,稍后试图诊断问题时,可以对该文件 ...

  8. mysql中括号_【Java程序猿必备系列】MySQL知识点总结

    点击 隔壁王小猿 关注公众号获取更多精彩JAVA文章 1.数据库的组成 2.MySQL数据类型 MySQL支持多种类型,大致可以分为三类:数值.日期/时间和字符串(字符)类型. 2.1 数值类型 My ...

  9. 阿里 mysql 架构_阿里java架构教你怎么用mysql怒怼面试官

    说一下mysql比较宏观的面试,具体咋写sql的这里就不过多举例了.后面我还会给出一个关于mysql面试优化的试题,这里主要说的索引和B+Tree结构,很少提到我们的集群配置优化方案. 1.索引是什么 ...

最新文章

  1. CMM能力成熟度模型
  2. Linux程序编译速度提高方法
  3. php 检测数组内是否有空值,PHP判断数组是否为空的常用方法
  4. html css纵向滑动列表,JS实现的简洁纵向滑动菜单(滑动门)效果
  5. android .a文件报毒,游戏开始文件,小A报毒!
  6. 机器学习与深度学习基础概念介绍
  7. wireshark分析UDP数据包
  8. 效果降临日历2009
  9. 二、从零开始学逆向之XCTF-logmein
  10. MATLAB实现的车牌定位系统
  11. java中逗号运算符的含义_逗号运算符什么时候有用?
  12. Java中接口的作用,为什么要写接口?
  13. flask自定义过滤器,flash,form表单
  14. 数值计算方法迭代法matlab实现
  15. 6-12 判断奇偶性 (10 分) 本题要求实现判断给定整数奇偶性的函数。
  16. 阅读材料精选 From-to-Date:2019.04.04~2019.04.29
  17. 校园BBS+校园贴吧 发帖 评论 点赞 回复 用户管理 好友管理 聊天的实现
  18. OrCAD中DRC的使用简要说明
  19. C语言中判断语句if
  20. mybatis choose when ==的应用。

热门文章

  1. 看了一下lua的实现
  2. BZOJ4377: [POI2015]Kurs szybkiego czytania
  3. English trip -- MC(情景课)3 C Do you have a sister?
  4. (转)Vue 爬坑之路(四)—— 与 Vuex 的第一次接触
  5. Activity生命周期(二)
  6. ——————————
  7. 你了解分层架构吗?给被PetShop“毒害”的朋友(转)
  8. ASP母版页与内容页不同目录 链接问题
  9. spring 扫描所有_自定义Spring事件监听机制
  10. android+坐标类,Android Path和PathMeasure类的使用之获取圆弧上的坐标值