android服务器 性能,Android性能优化(中)

Android性能优化

在上一篇中介绍了性能优化的概念、内存泄漏和性能优化方式

Android性能优化(上)

我们继续说说Android性能优化

数据库性能优化

索引

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

(1). 优点

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

(2). 缺点

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

使用场景

A.当某字段数据更新频率较低,查询频率较高,经常有范围查询(>, =, <=)或order by、group by发生时建议使用索引。并且选择度越大,建索引越有优势,这里选择度指一个字段中唯一值的数量/总的数量。

B. 经常同时存取多列,且每列都含有重复值可考虑建立复合索引

索引分类

直接创建索引和间接创建索引

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

CREATE INDEX mycolumn_index ON mytable (myclumn)

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

普通索引和唯一性索引

普通索引:CREATE INDEX mycolumn_index ON mytable (myclumn)

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

单个索引和复合索引

单个索引:索引建立语句中仅包含单个字段,如上面的普通索引和唯一性索引创建示例。

复合索引:又叫组合索引,在索引建立语句中同时包含多个字段,语句如:CREATE INDEX name_index ON username(firstname, lastname),其中firstname为前导列。

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

聚簇索引:物理索引,与基表的物理顺序相同,数据值的顺序总是按照顺序排列,语句为:CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) WITH ALLOW_DUP_ROW,其中WITH ALLOW_DUP_ROW表示允许有重复记录的聚簇索引

非聚簇索引:CREATE UNCLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn)

索引默认为非聚簇索引

使用规则

对于复合索引,把使用最频繁的列做为前导列(索引中第一个字段)。如果查询时前导列不在查询条件中则该复合索引不会被使用。

如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不支持存储过程::>_<::>

事务

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

原子提交

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

更优性能

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

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

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

public void insertWithOneTransaction() {

SQLiteDatabase db = sqliteOpenHelper.getWritableDatabase();

//开始一个事务

db.beginTransaction();

try {

for (int i = 0; i < 100; i++) {

db.insert(yourTableName, null, value);

}

// 设置当前事务成功

db.setTransactionSuccessful();

} catch (Exception e) {

e.printStackTrace();

} finally {

//结束事务

db.endTransaction();

}

}

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

其他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 = _ID;

public static final String HTTP_RESPONSE_TABLE_RESPONSE = "response";

public List getData() {

……

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

……

}

//优化为

public static final String HTTP_RESPONSE_TABLE_ID = _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);

……

}

异步线程

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.insert("你的表名", null, value);

handler.sendEmptyMessage(xx);

}

});

移动网络优化

一个网络请求可以简单分为连接服务器 -> 获取数据两个部分。

其中连接服务器前还包括DNS解析的过程;获取数据后可能会对数据进行缓存。

连接服务器优化策略

不用域名,用IP直连

省去 DNS 解析过程,DNS 全名 Domain Name System,解析意指根据域名得到其对应的 IP 地址。

如:http://www.codekk.com 的域名解析结果就是104.236.147.76。

首次域名解析一般需要几百毫秒,可通过直接向IP而非域名请求,节省掉这部分时间,同时可以预防域名劫持等带来的风险。

当然为了安全和扩展考虑,这个IP可能是一个动态更新的IP列表,并在IP不可用情况下通过域名访问。

服务器合理部署

配合上面说到的动态 IP 列表,支持优先级,每次根据地域、网络类型等选择最优的服务器IP进行连接。

对于服务器端还可以调优服务器的TCP拥塞窗口大小、重传超时时间(RTO)、最大传输单元(MTU)等。

获取数据优化策略

连接复用

节省连接建立时间,如开启keep-alive

Http 1.1 默认启动了keep-alive。对于Android来说默认情况下HttpURLConnection 和HttpClient都开启了keep-alive。

其他网络请求框架也可以进行相应配置

请求合并

即将多个请求合并为一个进行请求,比较常见的就是网页中的CSS Image Sprites。 如果某个页面内请求过多,也可以考虑做一定的请求合并。

减小请求数据大小

对于 POST 请求,Body 可以做 Gzip 压缩,如日志。

对请求头进行压缩

这个http 1.1不支持,spdy及http 2.0支持。http 1.1 可以通过服务端对前一个请求的请求头进行缓存,后面相同请求头用md5之类的id来表示即可。

CDN缓存静态资源

缓存常见的图片、JS、CSS 等静态资源。

减小返回数据大小

压缩

一般API数据使用Gzip压缩

精简数据格式

如JSON代替 XML,WebP代替其他图片格式

对于不同的设备不同网络返回不同的内容 如不同分辨率图片大小。

增量更新

需要数据更新时,可考虑增量更新。如常见的服务端进行bsdiff,客户端进行 bspatch。

大文件下载

支持断点续传,并缓存Http Resonse的ETag标识,下次请求时带上,从而确定是否数据改变过,未改变则直接返回304。

数据缓存

缓存获取到的数据,在一定的有效时间内再次请求可以直接从缓存读取数据。

现在的网络请求框架都可进行相应的缓存配置

今天周末,就说这么多(懒),祝大家周末Happy

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/352803.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jvm系列二之GC收集器

目录 参考概念理解并发和并行吞吐量GC垃圾收集器Serial New收集器Parallel New&#xff08;并行&#xff09;收集器Parallel Scavenge&#xff08;并行&#xff09;收集器Serial Old&#xff08;串行&#xff09;收集器Parallel Old&#xff08;并行&#xff09;收集器CMS收集器…

shell脚本中一些特殊符号

在shell中常用的特殊符号罗列如下&#xff1a; # ; ;; . , / \\ string| ! $ ${} $? $$ $* \"string\"* ** ? : ^ $# $ command{} [] [[]] () (()) || && {xx,yy,zz,...}~ ~ ~- & \\<...\\> - % ! # 井号 (…

java 并发执行_Java并发执行器的懒惰开发人员简介

java 并发执行如果我告诉您util.concurrent API自2004年起提供此类服务&#xff0c;我就会自欺欺人。但是&#xff0c;我想回顾一下一些很酷的功能。 并发专家&#xff0c;现在是时候关闭该窗口了。 所有其他人&#xff0c;请保持紧紧的乐趣。 你不会忘记你的根源 执行程序是具…

球球大作战测试服android版,球球大作战10.0体验服

在球球大作战10.0体验服中&#xff0c;2019球球们将迎来全新的冒险&#xff0c;多重外观&#xff0c;更加的绚丽夺目&#xff0c;探索新的地图&#xff0c;与不同的对手较量一番&#xff0c;无限吞噬&#xff0c;热血竞技&#xff0c;灵活的走位&#xff0c;搭配强力道具&#…

单线程的并发,协程

IO多路复用 作用:检测多个socket是否已经发生变化(是否已经连接成功/是否已经获取数据) setblocking(Flase) 让原本阻塞的变成非阻塞(不等待)状态 import socket import selectsk socket.socket() sk.setblocking(False) try:sk.connect(("www.baidu.com",80)) exce…

linux shell 字符串操作详解 (长度,读取,替换,截取,连接,对比,删除,位置 )

在做shell批处理程序时候&#xff0c;经常会涉及到字符串相关操作。有很多命令语句&#xff0c;如&#xff1a;awk,sed都可以做字符串各种操作。 其实shell内置一系列操作符号&#xff0c;可以达到类似效果&#xff0c;大家知道&#xff0c;使用内部操作符会省略启动外部程序等…

android.mk 模块编译,通过Android.mk添加一个编译模块到系统中的顺序如下

①LOCAL_PATH②CLEAR_VARS③LOCAL_SRC_FILES④LOCAL_CFLAGS(可选)⑤LOCAL_MODULE⑥LOCAL_STATIC_LIBRARIES(可选)⑦BUILD_XXX(12)Android.mk常用的变量变量名 说明LOCAL_PATH 用于确定源码所在的目录&#xff0c;最好把它放在CLEAR_VARS变量引用的前面&#xff0c;因为它不会被…

使用Spring Reactor Core进行分散收集

我在使用Netflix Rx-Java库方面有良好的工作经验&#xff0c;并且以前曾写过关于使用Rx-Java和Java 8 CompletableFuture解决分散式问题的博客。 在这里&#xff0c;我想探索使用Spring Reactor Core库应用相同的模式。 tldr –如果您熟悉Netflix Rx-Java&#xff0c;您已经很…

添加操作审计记录

1.所有操作审计记录 在环境变量/etc/profile中加入如下字段&#xff0c;可记录所有用户登录系统的操作 #history bash USERwhoami USER_IPwho -u am i 2>/dev/null| awk {print $NF}|sed -e s/[()]//g if [ "$USER_IP" "" ]; then USER_IPhostname fi …

android sharesdk分享功能,Android ShareSDK快速实现分享功能

第一步 &#xff1a;获取ShareSDK为了集成ShareSDK&#xff0c;您首先需要到ShareSDK官方网站注册并且创建应用&#xff0c;获得ShareSDK的Appkey&#xff0c;然后到SDK的下载页面下载SDK的压缩包&#xff0c;解压以后可以得到如下图的目录结构&#xff1a;ShareSDK在“ShareSD…

shell编程-分支语句

目标&#xff1a;完成这一章&#xff0c;你将能够作以下事情&#xff1a;描述条件分支语句中返回值的作用。 使用test命令来分析一个命令的返回值。 在shell程序中使用if和case结构。 1.返回值shell变量“&#xff1f;”中保存上一个被执行命令的返回值&#xff1a;0&#xff1…

android自定义表盘部件,Android自定义view仿支付宝芝麻信用表盘

演示效果实现步骤&#xff1a;1.画不同宽度和半径的内外圆弧2.通过循环旋转canvas&#xff0c;在固定位置绘制短线刻度&#xff0c;长线刻度&#xff0c;刻度文字3.绘制view中心几个文本&#xff0c;并调整位置4.实时更新当前旋转角度刷新小圆点位置&#xff1b;5.判断分数应该…

记录的详细操作

拷贝表拷贝结构 与数据create table copy_table select *from customer ;仅拷贝结构create table copy_table select *from customer where 0 > 1;共同点&#xff1a; 索引 描述&#xff08;自增&#xff09; 不能以下语法中记录的详细操作[] 表示可选的{}表示必选的增ins…

linux查看文件有多少行

使用wc命令 具体通过wc --help 可以查看。 如&#xff1a;wc -l filename 就是查看文件里有多少行 wc -w filename 看文件里有多少个word。 wc -L filename 文件里最长的那一行是多少个字。 wc命令 wc命令的功能为统计指定文件中的字节数、字数、行数, 并将统计结果显示输出。 …

java 消息通知_用Java弹出创建新的消息通知

java 消息通知首先创建JFrame作为弹出窗口。 在其中添加一些JLabel以包含信息&#xff0c;并在适当的位置分配它们&#xff0c;使其看起来像一条通知消息。 下面给出了示例代码&#xff1a; String message You got a new notification message. Isnt it awesome to have suc…

vs android 压缩,Android Studio是否压缩classes.dex文件?

看起来输出文件夹中apk文件的classes.dex与已安装的应用程序不同.我正在使用classes.dex文件来解决一些安全问题,所以通常我解压缩最终的apk文件并从classes.dex文件中获取信息.但是当我在运行时读取classes.dex文件时文件大小是如此不同. (8MB vs 46KB)应用程序本身工作得很好…

自己写的py文件中调用django models

import os os.environ[DJANGO_SETTINGS_MODULE] 项目名.settingsimport djangodjango.setup()from blog import modelsentry models.Entry.objects.get(pk1)tech_blog models.Blog.objects.get(name科技)print(entry, tech_blog) 转载于:https://www.cnblogs.com/dangrui072…

shell脚本 -d 是目录文件,那么-e,-f分别是什么?还有! -e这又是什么意思呢?

shell脚本 -d 是目录文件&#xff0c;那么-e&#xff0c;-f分别是什么?还有"&#xff01; -e"这又是什么意思呢&#xff1f; -e filename 如果 filename存在&#xff0c;则为真 -d filename 如果 filename为目录&#xff0c;则为真 -f filename 如果 filename为常规…

将Java应用程序作为Windows服务安装

这听起来像是您不需要的东西&#xff0c;但是有时候&#xff0c;当您分发最终用户软件时&#xff0c;可能需要将Java程序安装为Windows服务。 我之所以必须这样做&#xff0c;是因为我开发了一种用于公务员的工具 &#xff0c;可以自动将其Excel文件转换并将其推入我国的openda…

怎样实现banner自动播放html,纯CSS3实现banner图片自动轮播效果方式总结

自动轮播&#xff1a;实现切换图片&#xff0c;图片循环播放&#xff1b;鼠标悬停某张图片&#xff0c; 则暂停切换。css方法一、opacity控制透明度实现轮播效果依照需求咱们选择用CSS3的animation动画进行实现&#xff1b;transition动画须要触发才能启动&#xff0c;html因此…