精华内容
下载资源
问答
  • MySQL大表优化方案

    万次阅读 多人点赞 2020-11-02 13:51:07
    方案概述 一、数据库设计及索引优化 MySQL数据库本身高度灵活,造成性能不足,严重依赖开发人员的表设计能力以及索引优化能力,在这里给几点优化建议 时间类型转化为时间戳格式,用int类型储存,建索引增加查询效率 ...

    背景

    阿里云RDS FOR MySQL(MySQL5.7版本)数据库业务表每月新增数据量超过千万,随着数据量持续增加,我们业务出现大表慢查询,在业务高峰期主业务表的慢查询需要几十秒严重影响业务

    方案概述

    20201030141518

    一、数据库设计及索引优化

    MySQL数据库本身高度灵活,造成性能不足,严重依赖开发人员的表设计能力以及索引优化能力,在这里给几点优化建议

    • 时间类型转化为时间戳格式,用int类型储存,建索引增加查询效率
    • 建议字段定义not null,null值很难查询优化且占用额外的索引空间
    • 使用TINYINT类型代替枚举ENUM
    • 存储精确浮点数必须使用DECIMAL替代FLOAT和DOUBLE
    • 字段长度严重根据业务需求来,不要设置过大
    • 尽量不要使用TEXT类型,如必须使用建议将不常用的大字段拆分到其它表
    • MySQL对索引字段长度是有限制的, innodb引擎的每个索引列长度默认限制为767字节(bytes),所有组成索引列的长度和不能大于3072字节(mysql8.0单索引可以创建1024字符)
    • 大表有DDL需求时请联系DBA

    最左索引匹配规则

    顾名思义就是最左优先,在创建组合索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。复合索引很重要的问题是如何安排列的顺序,比如where后面用到c1, c2 这两个字段,那么索引的顺序是(c1,c2)还是(c2,c1)呢,正确的做法是,重复值越少的越放前面,比如一个列 95%的值都不重复,那么一般可以将这个列放最前面

    • 复合索引index(a,b,c)
    • where a=3 只使用了a
    • where a=3 and b=5 使用了a,b
    • where a=3 and b=5 and c=4 使用了a,b,c
    • where b=3 or where c=4 没有使用索引
    • where a=3 and c=4 仅使用了 a
    • where a=3 and b>10 and c=7 使用了a,b
    • where a=3 and b like ‘xx%’ and c=7 使用了a,b
    • 其实相当于创建了多个索引:key(a)、key(a,b)、key(a,b,c)

    二、数据库切换到PloarDB读写分离

    PolarDB是阿里云自研的下一代关系型云数据库,100%兼容MySQL存储容量最高可达100 TB,单库最多可扩展到16个节点,适用于企业多样化的数据库应用场景。PolarDB采用存储和计算分离的架构,所有计算节点共享一份数据,提供分钟级的配置升降级、秒级的故障恢复、全局数据一致性和免费的数据备份容灾服务。

    • 集群架构,计算与存储分离
      PolarDB采用多节点集群的架构,集群中有一个Writer节点(主节点)和多个Reader节点(只读节点),各节点通过分布式文件系统(PolarFileSystem)共享底层的存储(PolarStore)
    • 读写分离
      当应用程序使用集群地址时,PolarDB通过内部的代理层(Proxy)对外提供服务,应用程序的请求都先经过代理,然后才访问到数据库节点。代理层不仅可以做安全认证和保护,还可以解析SQL,把写操作(例如事务、UPDATE、INSERT、DELETE、DDL等)发送到主节点,把读操作(例如SELECT)均衡地分发到多个只读节点,实现自动的读写分离。对于应用程序来说,就像使用一个单点的数据库一样简单。

    在离线混合场景:不同业务用不同的连接地址,使用不同的数据节点,避免相互影响

    20201029160013

    Sysbench性能压测报告:

    • PloarDB 4核16G 2台

    20201029160525
    20201029160550

    • PloarDB 8核32G 2台

    20201029160755
    20201029160845

    三、分表历史数据迁移到MySQL8.0 X-Engine存储引擎

    分表业务表保留3个月数据(这个根据公司需求来),历史数据按月分表到历史库X-Engine存储引擎表, 为什么要选用X-Engine存储引擎表,它有什么优点?

    1. 节约成本, X-Engine的存储成本约为InnoDB的一半
    2. X-Engine分层存储提高QPS, 采用层次化的存储结构,将热数据与冷数据分别存放在不同的层次中,并默认对冷数据所在层次进行压缩

    X-Engine是阿里云数据库产品事业部自研的联机事务处理OLTP(On-Line Transaction Processing)数据库存储引擎。
    X-Engine存储引擎不仅可以无缝对接兼容MySQL(得益于MySQL Pluginable Storage Engine特性),同时X-Engine使用分层存储架构。因为目标是面向大规模的海量数据存储,提供高并发事务处理能力和降低存储成本,在大部分大数据量场景下,数据被访问的机会是不均等的,访问频繁的热数据实际上占比很少,X-Engine根据数据访问频度的不同将数据划分为多个层次,针对每个层次数据的访问特点,设计对应的存储结构,写入合适的存储设备

    • X-Engine使用了LSM-Tree作为分层存储的架构基础,并进行了重新设计:
    • 热数据层和数据更新使用内存存储,通过内存数据库技术(Lock-Free index structure/append only)提高事务处理的性能。
    • 流水线事务处理机制,把事务处理的几个阶段并行起来,极大提升了吞吐。
    • 访问频度低的数据逐渐淘汰或是合并到持久化的存储层次中,并结合多层次的存储设备(NVM/SSD/HDD)进行存储。
    • 对性能影响比较大的Compaction过程做了大量优化:
    • 拆分数据存储粒度,利用数据更新热点较为集中的特征,尽可能的在合并过程中复用数据。
    • 精细化控制LSM的形状,减少I/O和计算代价,有效缓解了合并过程中的空间增大。
    • 同时使用更细粒度的访问控制和缓存机制,优化读的性能。

    20201029162440

    四、阿里云PloarDB MySQL8.0版本并行查询

    分表之后我们的数据量依然很大,并没有完全解决我们的慢查询问题,只是降低了我们业务表的体量,这部分慢查询我们需要用到PolarDB的并行查询优化

    PolarDB MySQL 8.0重磅推出并行查询框架,当您的查询数据量到达一定阈值,就会自动启动并行查询框架,从而使查询耗时指数级下降
    在存储层将数据分片到不同的线程上,多个线程并行计算,将结果流水线汇总到总线程,最后总线程做些简单归并返回给用户,提高查询效率。
    并行查询(Parallel Query)利用多核CPU的并行处理能力,以8核32 GB配置为例,示意图如下所示。

    20201029163124

    并行查询适用于大部分SELECT语句,例如大表查询、多表连接查询、计算量较大的查询。对于非常短的查询,效果不太显著。

    并行查询用法,使用Hint语法可以对单个语句进行控制,例如系统默认关闭并行查询情况下,但需要对某个高频的慢SQL查询进行加速,此时就可以使用Hint对特定SQL进行加速。

    SELECT /+PARALLEL(x)/ … FROM …; – x >0

    SELECT /*+ SET_VAR(max_parallel_degree=n) */ * FROM … // n > 0

    查询测试:数据库配置 16核32G 单表数据量超3千万

    没加并行查询之前是4326ms,加了之后是525ms,性能提升8.24倍

    lALPDhmOtqINirTNAl_NBIw_1164_607

    lALPDgQ9vsVjxDbNAl7NBHk_1145_606

    五、交互式分析Hologre

    大表慢查询我们虽然用并行查询优化提升了效率,但是一些特定的需求实时报表、实时大屏我们还是无法实现,只能依赖大数据去处理。
    这里推荐大家阿里云的交互式分析Hologre(
    https://help.aliyun.com/product/113622.html)

    20201030151537

    六、后记

    千万级大表优化是根据业务场景,以成本为代价优化的,不是一上来就数据库水平切分扩展,这样会给运维和业务带来巨大挑战,很多时候效果不一定好,我们的数据库设计、索引优化、分表策略是否做到位了,应该根据业务需求选择合适的技术去实现。

    展开全文
  • H5性能优化方案

    千次阅读 2016-08-17 18:06:07
    原本H5的渲染性能就不及native的app,如果不把性能优化做起来,将极大地影响用户使用产品的积极性。用户感受当用户能够在1-2秒内打开H5页面,看到信息的展示,或者能够开始进行下一步的操作,用户会感觉速度还好,...

    H5性能优化意义

    对于一个H5的产品,功能无疑很重要,但是性能同样是用户体验中不可或缺的一环。原本H5的渲染性能就不及native的app,如果不把性能优化做起来,将极大地影响用户使用产品的积极性。

    用户感受

    当用户能够在1-2秒内打开H5页面,看到信息的展示,或者能够开始进行下一步的操作,用户会感觉速度还好,可以接受;而页面如果在2-5秒后才进入可用的状态,用户的耐心会逐渐丧失;而如果一个界面超过5秒甚至更久才能显示出来,这对用户来说基本是无法忍受的,也许有一部分用户会退出重新进入,但更多的用户会直接放弃使用。

    一秒钟法则

    移动互联网的架构、通讯机制,与有线网络有着巨大的差异,这也给H5的开发带来了很大的挑战。

    10.jpg

    这是一张手机端接入服务器的流程。

    首先,手机要通过无线网络协议,从基站获得无线链路分配,才能跟网络进行通讯。 无线网络基站、基站控制器这方面,会给手机进行信号的分配,已完成手机连接和交互。 获得无线链路后,会进行网络附着、加密、鉴权,核心网络会检查你是不是可以连接在这个网络上,是否开通套餐,是不是漫游等。核心网络有SGSN和GGSN,在这一步完成无线网络协议和有线以太网的协议转换。 再下一步,核心网络会给你进行APN选择、IP分配、启动计费。 再往下面,才是传统网络的步骤:DNS查询、响应,建立TCP链接,HTTP GET,RTTP RESPONSE 200 OK,HTTP RESPONSE DATA,LAST HTTP RESPONSE DATA,开始UI展现。

    可见,通过运营商的网络上网,情况比较复杂,经过的节点太多;运营商的网络信号强度变化频繁,连接状态切换快;网络延迟高、丢包率高;网络建立连接的代价高,传输速度快慢不等(从2G到4G,相差很大)。

    而我们优化的目标,就是所谓的一秒钟法则,即达成以下的标准:

    • 2g网络:1秒内完成dns查询、和后台服务器建立连接
    • 3g网络:1秒内完成首字显示(首字时间)
    • wifi网络:1秒内完成首屏显示(首屏时间)

    优化方案

    资源加载

    首屏加载

    用户从点击按钮开始载入网页,在他的感知中,什么时候是“加载完成”?是首屏加载,即在可见的屏幕范围内,内容展现完全,loading进度条消失。因此在H5性能优化中,一个很重要的目的就是尽可能提升这个“首屏加载”的时间,让它满足“一秒钟法则”。

    按需加载

    首先要明确,按需加载虽然能提升首屏加载的速度,但是可能带来更多的界面重绘,影响渲染性能,因此要评估具体的业务场景再做决定。

    Lazyload

    Lazyload,即延迟加载,这并不是一个新的技术,在PC时代也是非常常用的一种性能优化手段。这个方案的原则是让屏幕外,或者不影响整体效果显示的图片、背景等资源,在界面就绪之后再进行网络加载。

    滚屏加载

    滚屏加载是一种常见的无刷新动态加载数据的方案,通常用在列表形式数据展示中。一方面,数据不是通过翻页进行加载,这样就避免了再一次请求和渲染整个页面;另一方面,数据显示的数量是受限的,例如第一次只请求了10条数据,也就只需要渲染这10条数据,下拉滚屏的时候,再去获得下面10条数据。

    Media Query(响应式加载)

    响应式设计是现在网站设计的一个流行趋势,随着移动互联网的发展,这项技术也越来越受到重视。通过这项技术,我们能够方便地控制资源的加载与显示,例如说在分辨率不同的手机上,分别使用不同的css,加载不同大小的图片资源。 方案参考:http://www.poluoluo.com/jzxy/201206/167034.html

    第三方资源异步加载

    第三方资源有的时候不可控,比如说页面统计、地图显示、分享组件等,这些第三方资源使用的时候要慎重选择,充分考察它们对于性能的影响,使用异步加载的方式进行,防止第三方资源的使用影响到页面本身的功能。

    Loading进度条

    在加载时间较长的时候,务必要让用户明确感知到加载完成的提示,通常是在加载过程中显示Loading的进度条,加载完成的时候隐藏它。从心理上,这会让用户有一种“期盼感”,而不至于太过枯燥。

    对于一些重量级的H5应用,例如游戏,开始前需要加载很多资源才能让后面的游戏过程更为流畅,一个带百分比进度显示的进度条就更加重要。

    避免30*/40*/50*的http status

    • 200是一个正常的response,我们在浏览器中打开一个网页(后面会讲如何针对移动端进行调试),还会看到304,即命中浏览器缓存。这两种状态是正常的http status。

    • 302、301跳转是常见的跳转,尤其前一种,在我们进行鉴权的时候有时会用到,但这个做法要尽可能地优化,一个页面访问,最多只进行一次302跳转即可,切忌频繁地跳转。

    • 404、500,我们对自己开发的代码比较注意,一般不会发生,但是有的时候,加载第三方库,尤其是第三方库中有自己load组件的操作,这时,404和500错误可能会在你不知不觉的时候发生。例如钉钉的第三方微应用中,就遇到过dojo的组件加载问题,加载的一些子组件失败了,但是又没有影响页面显示,这就很容易被忽略。后面也会再讲,如何去测试和发现这样的隐患。

    Favicon.ico

    如果我们没有设置图标ico,则会加载默认的图标:域名目录下的favicon.ico。很多开发者没有注意到这一点,就会导致这个请求404或者500。

    通常,我们在应用内部打开网页,不会显示这个图标出来(除非放到浏览器中显示网页),我们需要保证这个图标存在,尽可能地小(一般4KB以下),并且设置一个较长的缓存过期时间。

    图片的使用

    格式选择

    显示效果较好的图片格式中,有webp、jpg和png24/32这几种常见的图片格式。一般来说,webp的图片最小,但在iOS或者android4.0以下的系统中可能会有兼容性问题需要解决。

    • Jpg是我们最常使用的方案,大小适中,解码速度快,兼容性问题也基本不存在,是我们在H5的应用中使用起来性价比最高的方案。

    • Png24或png32,一般来说,显示效果肯定会比jpg更好,但是实际上人眼很难感知出来,所以在H5应用中要避免这种格式的大图片。

    对于少量的图片,推荐用智图或者tinypng等工具来帮助自己选择合适的大小、格式。

    像素控制

    在H5应用中,图片的像素要严格控制,一般来说不建议宽度超过640px。

    小图片合并

    在html网页中,如果有多个小图片需要加载,不妨试试CSS Sprites方案,尤其是一些基本不变,大小差不多的操作类型图标。

    避免html代码中的大小重设

    在html或者css中,如果有类似width: **px这样的代码,就要注意看一看了,如果说图片显示的效果是宽度100px,而下载的图片却是200px宽度,那这大小基本上就是所需要的4倍面积了,所以在H5应用中,使用图片的一个原则就是需要显示成多大,就下载多大的资源。

    避免DataURL

    DataURL是用Base64的方式,将图片变成一串文本编码放入代码的方式。这种方式有好处,因为它可以减少一次http交互的请求,对于一些体积特别小的图片,或者是动态生成的图片可以考虑使用。但在H5应用中,一般情况下,我们都是需要避免DataURL的,因为它的数据体积通常比二进制图片的格式大1/3,而且它不会被浏览器缓存,每次页面刷新都需要重新加载这部分数据。

    使用图片的替代(css3, svg, iconfont)

    CSS3和svg可以更好地使用GPU进行渲染加速,而且会避免增加图片资源导致的http请求增加。例如一些div的圆角效果,就完全可以用用css来实现。

    Iconfont,可以认为是一种矢量类型的操作字体。如果页面中有较多的操作图标,可以考虑使用iconfont来替代图片资源。

    域名/服务端部署

    Gzip

    服务端要开启Gzip压缩。

    资源缓存,长cache

    合理设置资源的过期时间,尤其对一些静态的不需要改变的资源,将其缓存过期时间设置得长一些。

    分域名部署(静态资源域名)

    将动态资源和静态资源放置在不同的域名下,例如图片,放在自己特定的域名下。这样的好处是,静态资源请求时,不会带上动态域名中所设置的cookie头信息,从而减少http请求的大小。

    减少Cookie

    尽量减少Cookie头信息的大小,因为这部分数据使用的是上行流量,上行带宽更小,所以传输速度更慢,因此要尽量精简其大小。

    CDN加速

    部署CDN服务器,或者使用第三方的CDN加速服务,优化不同地域接入网站的带宽速度。

    代码资源

    Javascript, CSS合并

    尽量将所有的js和css合并,减少资源请求的次数。

    外联使用js, css

    外联使用js和css,这样可以有效地利用缓存,避免html页面刷新后重新加载这部分代码。

    压缩html, js, css

    压缩代码,尤其是js和css资源,压缩后的大小可以降低至原来的1/3以下,有效节约流量。

    资源的版本更新

    库js、css通常不会更新,但是我们的业务js和css可能会有更新,如果命中浏览器缓存,可能会让一些新的特性不能及时展现,甚至可能导致逻辑上的冲突。

    因此对于这些js、css的资源引入,最好用版本号或者更新时间来作为后缀,这样的话,后缀不变,命中缓存;后缀改变,浏览器自动更新最新的代码。

    Css位置

    CSS要放到html代码的开头的head标签结束前。如果网页是动态生成的,那么在head代码完成后可以强制输出(例如php的flush()操作),这样的话,浏览器就会更快地解析出来head中的内容,开始下载css文件资源。

    Js位置

    Js放到前,这样的话,js的加载不会影响初始页面的渲染。

    代码规范

    避免空src

    图片设置为空的src地址,在某些浏览器中可能会导致增加一个无效的http请求,因此要避免。

    避免css表达式

    可能会让页面多次执行计算,造成卡顿等性能问题。

    避免空css规则

    降低css渲染计算的成本

    避免直接设置元素style

    直接设置style属性,一方面在html代码中不利于缓存,另一方面也不利于样式的复用,因此要避免,通过指定id或者class的方式,在css代码块中进行样式调整。

    服务端接口

    接口合并

    如果页面需要请求两部分以上的数据接口,建议将其合并,否则会增加一次http请求。

    减少接口数据量

    有的时候,服务端会把一些无关紧要的数据返回回来,尤其是类似于更新时间、状态等信息,如果在客户端不影响内容的逻辑展示,不妨在接口返回的数据中直接去掉这些内容。

    缓存

    缓存接口数据,在一些数据新旧敏感性不高的场景下很有作用,在非首次加载数据时候优先使用上次请求来的缓存数据,可以让页面更加快速地渲染出来,而不用等待一个新的http请求结束之后再渲染。这一点我们在后面还会再次提及。

    其他一些建议

    • 合理使用css
      • 正确使用Display属性 Display属性会影响页面的渲染,因此请合理使用
      • display:inline后不应该再使用width、height、margin、padding以及float
      • display:inline-block后不应该再使用float
      • display:block后不应该再使用vertical-align
      • display:table-*后不应该再使用margin或者float
      • 不滥用float
      • 不声明过多的font-size
      • 值为0时不需要单位
      • 标准化各种浏览器前缀
      • 无前缀应放在最后
      • CSS动画只用 (-webkit- 无前缀)两种即可
      • 其它前缀为 -webkit- -moz- -ms- 无前缀 四种,(-o-Opera浏览器改用blink内核,所以淘汰)
    • 选择器
      • 避免让选择符看起来像是正则表达式。高级选择器不容易读懂,执行耗时也长
      • 尽量使用ID选择器
      • 尽量使用css3动画
    • 资源加载
      • 使用srcset
      • 首次加载不超过1024KB(或者可以说是越小越好)
    • html和js
      • 减少重绘和回流
      • 缓存dom选择和计算
      • 缓存列表.length
      • 尽量使用事件代理,避免批量绑定事件
      • 使用touchstart,touchend代替click
      • Html使用viewport
      • 减少dom节点
      • 合理使用requestAnimationFrame动画代替setTimeOut
      • 适当使用Canvas动画
      • TouchMove, Scroll事件会导致多次渲染

    更快一步

    前面的很多建议与普通的PC端web网页的开发是一致的,但是在移动互联网应用下,仅仅做到这些,可能只有60分,那么怎样才能得到80分甚至更高?

    单页应用

    钉钉的审批微应用,使用的就是单页架构。在这种架构下,基本不存在页面跳转的等待时间,只需要执行js逻辑触发界面变化,最多进行一次网络请求,获得服务端数据,其他资源均不需要再次请求。

    资源离线

    再快的网络交互,毕竟也是跨越了数个网络节点,因此一张图片、一个js,优化到了极致,也照样可能需要几百毫秒的时间来获得。因此想要打破这个极限,就要使用资源离线的策略。

    在钉钉的微应用中,就使用了这样的一个“离线包”策略。一些固定的图片、js库等,被打包放入app中(或根据需要,在app启动的时候进行下载更新)。

    微应用中,网页代码里面加载网络资源的需求,就变成了直接加载本地文件,速度自然得到再一次巨大的提升。

    本地数据持久化和更新机制(版本管理)

    对于一些时效性没有那么高的数据,可以考虑将接口数据缓存。那么页面的渲染将变成这样的流程:

    20.png

    而非首次进入界面,流程如下:

    30.png

    可以看出,在非首次进入界面的时候,页面不需要等待网络数据返回,就可以进行界面渲染,渲染的初始数据来自于本地的缓存,页面可以“秒开”。而当服务端的数据返回之后,本地的渲染会再次更新,缓存也被更新。

    采用这样的方案有利有弊,好处显而易见,首屏加载的速度简直太快了——静态资源来自本地,数据接口来自本地,这在2G、3G或者其他网络速度较慢的时候,也可以让用户在极短的时间内就看到内容。但是这种方案也并非万能。

    1. 首次加载不可避免,还是会请求网络。
    2. 服务端有更新的时候,客户端不能够快速感知,页面可能还停留在一个“旧的版本”上,尤其是网络速度较慢时,可能还是需要经过好几秒,页面才会更新至最新版本。因此如果应用对数据的新旧很敏感的话,这种方案就不适合
    3. 数据更新后,需要重新渲染界面,界面刷新的性能消耗比正常情况更多,而且增加了程序的复杂度,容易出错。

    预加载

    有时,我们能够通过用户的行为统计,预判出用户下一步可能进行的操作。假设,我们统计出来针对某个微应用,用户首页渲染完成之后,大部分会点击列表中的第一个项目查看详情。那么在首页渲染完成之后,我们就可以先预先加载第一个项目的部分内容,那么针对这部分用户,他们实际点击之后,立即就能看到新的页面中的内容。

    当然,这个方式也并不是在所有场景下都使用。一方面,需要做好充分的用户调研,掌握用户的使用习惯;另一方面,对于小部分用户而言,预加载所带来的就是不必要的流量消耗。

    测试方案

    工具准备

    Chrome

    在功能测试中,我们通常可以用chrome来测试不同的分辨率下,或是不同的设备上,网页的展现情况。在我们做性能优化的时候,也可以用这种方式来进行调试,方便地观察在特定设备上,静态资源是否按照我们想象的那样去加载了。40.png

    例如,我们想看下百度首页在某个设备下的表现。 通过F12进入控制台,点击图中的短箭头标示出来的那个设备图标,然后就可以在Device和Network中选择不同的设备和网络状况。50.png

    例如iphone5下,这个地图的图标,明显就可以看到是用iconfont来实现的效果。

    当然,这个功能也仅仅是一种模拟,通过控制屏幕分辨率、UserAgent等来模拟设备请求,在实际的设备上,又该怎么查看呢?

    还是Chrome,我们在地址栏中输入chrome://inspect (注意:Android版本需要是4.4+,并且应用中的WebView必须进行相应的调试声明配置)60.png

    在这里点击inspect,则可进入我们熟悉的F12控制台界面,只不过debug的对象变成了我们在手机应用中的网页。70.png

    输入performance.timing.domComplete - performance.timing.navigationStart,就可以打印出网页加载的时间,domComplete表示所有的处理都已完成并且所有的附属资源都已经下载完毕。navigationStart表示开始加载新页面。两者相减,就代表这个网页完成渲染所需要的时间了。

    同样地,我们可以在Elements tab中,debug网页,查看各个资源的使用,在Network中,看看加载了哪些资源,是否都做过了压缩。

    然而,这种方式,还是有一定缺陷。 1. 如果打开网页经过了跳转,那么我们只能在这里看到最后一个url页面的加载情况。 2. 第一次打开页面的时候,在Network中,默认是不显示请求的详情的,当我们选择了preserve log upon navigation之后才会捕获,因此首次进入页面的加载情况,我们就很难获得了。

    那么有没有一种方法,让我们能够更方便地去查看首次访问时,各种资源的加载使用情况呢?

    Charles

    Charles Proxy,可以说是H5测试的一个神器。 它的作用是在PC端开启一个代理服务器,手机连到这个代理服务器上之后,所有的http请求就都可以在这里看得清清楚楚。经过配置证书选项,https的请求也可以正常查看。80.png

    从图中,我们明显可以看到,有一些404的异常请求,这些都将对我们H5应用的性能造成影响。 如果我们发现有一些资源的Duration比较大,那这些可能是服务端响应太慢,自然也可以作为我们优化的依据。

    测试标准

    在钉钉的测试中,形成了一套标准。

    |指标项|遵循的原则|优先级|检查项|说明| |:-|:-|:---|:---|:--| |内存|内存无泄漏|P0|主功能页面反复打开,功能的重复调用,内存无泄漏| 可以使用sysdump,也可以用我们开发的perfeasy工具进行观察| | | |P1|主功能页面,持续操作,退出后,内存占用不超过总内存的5%|perfeasy| |CPU|减少无端的CPU使用|P1|灭屏,静置2分钟,在5分钟内CPU使用平均1%|adb连接后, 使用top命令| ||||主干功能正常操作CPU占用不超过60%, 持续5秒|perfeasy| |电量|避免无端电量消耗|P0|灭屏状态下,无线程持续运行|一般来说, 静置cpu正常, 这一项就没有问题| ||||灭屏,window.setTimeout()方法停止|一般来说, 静置cpu正常, 这一项就没有问题同上| ||||灭屏,window.setInterval()方法停止|同上| ||||ajax超时时间设置为5000ms以内|结合代码| ||||ajax无retry逻辑|结合代码| |资源|资源的正确使用|P0|是否存在资源的重复拉取|charles| |||P1|H5页面首屏总大小不超过200K|charles, chrome| |||P1|抓包检查(js/css/html)代码去除了空格/注释,JS文件变量名变成a/b等代替|charles, chrome| |||P1|H5引用的单张图片小于60K|charles, chrome
    如果影响了显示质量, 可酌情调整| |流畅度|确保给到用户流畅的展示体验|P1|流畅的实时动画展示,avgFPS>=45|perfeasy| |时延|确保给到用户流畅的切换体验|P0|wifi网络下,首次进入页面onload时间<1000ms|Chrome| |时延|确保给到用户流畅的切换体验|P0|wifi网络下,首次进入页面onload时间<1000ms|Chrome| ||||wifi网络下,非首次进入页面onload时间<500ms|Chrome| ||||3G正常网络, 首次进入页面onload时间<2000ms|chrome, 树莓派模拟3G| ||||3G正常网络, 非首次进入页面onload时间<1000ms|chrome, 树莓派模拟3G|

    经典案例

    图片未优化

    通过charles可以方便地进行测试。 从请求监控的情况看,有一张图片超过了60KB,宽度640px,但是在应用中,实际显示的是一张小缩略图,是通过代码控制让它显示成小图的,因此修改方案很简单,将所有头像的图片均改为获取120px宽度的即可。90.png

    按需加载

    • 钉钉的教学页面

      • 多个slide页面, 每个页面有2-3个图片, 其中有一个是大图显示
      • 图片是客户提供的, 最大的图片大约是300KB以上
      • 第一次进入页面后, 所有slide的图片均进行加载
      • 3G网络下, loading的图标大约持续6000ms后才会消失
    • 优化方案

      • 尽可能优化图片, 但是压缩后发现噪点明显增加, 影响了显示效果
      • 修改加载方案, 第一次进入后, 只加载本页的图片
      • loading时间降低至1秒左右

    原文 http://ddtalk.github.io/blog/2015/09/07/dingding-first/
    展开全文
  • 架构优化方案

    千次阅读 2019-05-24 10:08:55
    1.业务拆分方法:根据业务属性进行垂直切分,划分为产品子系统,购物子系统,支付子系统,评论子系统,客服子系统,接口子系统等 产品子系统(核心) 线路 保险 签证 酒店 景区 供应商子系统(核心) 专门负责供应商...

    业务拆分

    1.业务拆分方法:根据业务属性进行垂直切分,划分为产品子系统,购物子系统,支付子系统,评论子系统,客服子系统,接口子系统等

    产品子系统(核心)
    线路
    保险
    签证
    酒店
    景区

    供应商子系统(核心)
    专门负责供应商对接
    供应商合同签署

    下单子系统(核心)
    门店下单
    官网下单
    其他下单

    支付子系统(核心)
    负责所有的支付流程

    评论子系统(非核心)
    订单评论
    导游评论
    内部考核评价

    接口子系统(非核心)
    电子合同接口
    江泰保险接口
    客服子系统(非核心)

    2.业务拆分作用

    提升为子系统可以由专门的团队和部门负责,解决模块之间的耦合以及扩展性问题

    每个子系统单独部署,避免集中部署导致一个应用挂了,全部应用不可用的问题

    3.等级定义作用

    在流量大的时候,对关键应用进行保护,实现优雅降级或者服务熔断,保护关键应用不受影响。

    双十一的时候,淘宝的选择收货地址模块直接崩了,但是不会影响正常下单,这就是经典的拆分和服务熔断实现
    在这里插入图片描述
    在这里插入图片描述

    • 每个应用单独部署
    • 核心系统和非核心系统组合部署

    应用集群部署(分布式,集群,负载均衡)

    分布式部署:将业务拆分之后的应用单独部署,应用直接通过RPC进行远程通信

    集群部署:电商网站的高可用要求,每个应用至少部署两台服务器进行集群部署

    负载均衡:是 高可用系统必须的,一般应用通过负载均衡实现高可用,分布式系统通过内置的负载均衡实现高可用,关系型数据库通过主备方式实现高可用。
    在这里插入图片描述
    前端对于不同模块的请求应该分发到不同的负载均衡器上,这个应该是预先设置好的,如果为了统一期间,应该使用一个统一的后台接口,作为负载均衡器的分发器,但是单个集中网关会造成性能瓶颈。

    多级缓存

    缓存按照存放的位置分为本地缓存和分布式缓存。
    一般设计为二级缓存
    一级缓存为本地缓存
    二级缓存为分布式缓存
    一级缓存: 缓存数据字典,和常用热点数据等基本不可变/有规则变化的信息,
    二级缓存: 缓存需要的所有缓存。当一级缓存过期或不可用时,访问二级缓存的数据。如果二级缓存也没有,则访问数据库。
    在这里插入图片描述
    根据业务特性可使用以下缓存过期策略:缓存自动过期;缓存触发过期;

    单点登录(分布式Session)

    系统分割为多个子系统,独立部署后,会遇到会话管理问题,一般可以采用Session同步,Cookie,分布式Session方式。电商一般使用的是分布式Session。
    在这里插入图片描述
    流程说明

    1.用户第一次登录的时候,将会话信息写入分布式Session
    2.用户再次登录的时候,获取分布式Session,是否有会话信息,如果没有就跳转到登陆页面
    3.一般采用Cache中间件,建议使用Redis,因为有持久化功能,方便分布式Session宕机后,可以从持久化存储中加载会话信息。(Redis一般使用的是主从的模式,主和从之间通过写入日志来同步,主服务器宕机,从会通过选举机制来选出新Master
    4.存入会话时,可以设置会话保持的时间,比如15分钟,超过后自动超时。

    数据库集群(读写分离,分库分表)

    为了存储海量数据,高可用和高性能一般采用冗余的方式进行系统设计。
    一般有两种方式:

    1.读写分离:适用于读大于写比例的场景,可采用一主一备,一主多备或者多主多备
    2.分库分表
    业务拆分后,每个子系统需要单独的库
    单独库太大的话,可以再次细化,为商品分类库产品库等
    分库之后要分表,垂直划分或者水平划分,可以按照id时间等水平切割,高级用法是采用一致性hash算法。

    在分库分表的基础上进行读写分离

    服务化

    将多个子系统公用的功能/模块,进行抽取,作为公用服务使用。比如本案例的会员子系统就可以抽取为公用的服务。

    所谓将系统分开,也就是Controller分开,不同的Controller形成一个子系统,专门处理相关的业务,Service可以做成微服务,尤其是公共的服务(这就要用到dubbo)
    在这里插入图片描述

    消息队列

    消息队列可以解决子系统/模块之间的耦合,实现异步,高可用,高性能的系统。是分布式系统的标准配置。本系统中消息队列主要应用在购物,配送环节。

    1. 用户下单后,直接写入消息队列后返回客户端
    2. 库存子系统:读取消息队列信息,完成减库工作
    3. 配送子系统:读物消息队列信息,进行配送
      在这里插入图片描述

    目前使用较多的MQ有Active MQ,Rabbit MQ,Zero MQ,MS MQ等,需要根据具体的业务场景进行选择。建议可以研究下Rabbit MQ和kafka。

    展开全文
  • ListView优化方案

    千次阅读 2015-03-10 13:26:23
    一、复用convertView,减少findViewById的次数1、优化一:复用convertViewAndroid系统本身为我们考虑了ListView的优化问题,在复写的Adapter的类中,比较重要的两个方法是getCount()和getView()。界面上有多少个条...

    一、复用convertView,减少findViewById的次数

    1、优化一:复用convertView

    Android系统本身为我们考虑了ListView的优化问题,在复写的Adapter的类中,比较重要的两个方法是getCount()和getView()。界面上有多少个条显示,就会调用多少次的getView()方法;因此如果在每次调用的时候,如果不进行优化,每次都会使用View.inflate(….)的方法,都要将xml文件解析,并显示到界面上,这是非常消耗资源的:因为有新的内容产生就会有旧的内容销毁,所以,可以复用旧的内容。
    优化:
    在getView()方法中,系统就为我们提供了一个复用view的历史缓存对象convertView,当显示第一屏的时候,每一个item都会新创建一个view对象,这些view都是可以被复用的;如果每次显示一个view都要创建一个,是非常耗费内存的;所以为了节约内存,可以在convertView不为null的时候,对其进行复用

    public View getView(int pos, View convertView,
    ViewGroup parent){
    if (convertView == null) {
    convertView = mInflater.inflate(
    R.layout.list_item, null);
    }
    ((TextView) convertView.findViewById(R.id.text)).
    setText(DATA[pos]);
    ((ImageView) convertView.findViewButId(R.id.icon)).
    setImageBitmap((pos & 1) == 1 ? mIcon1 : mIcon2);
    return convertView;
    }

    2、优化二:缓存item条目的引用——ViewHolder

    findViewById()这个方法是比较耗性能的操作,因为这个方法要找到指定的布局文件,进行不断地解析每个节点:从最顶端的节点进行一层一层的解析查询,找到后在一层一层的返回,如果在左边没找到,就会接着解析右边,并进行相应的查询,直到找到位置。因此可以对findViewById进行优化处理,需要注意的是:
    

    特点:xml文件被解析的时候,只要被创建出来了,其孩子的id就不会改变了。根据这个特点,可以将孩子id存入到指定的集合中,每次就可以直接取出集合中对应的元素就可以了。
    优化:
    在创建view对象的时候,减少布局文件转化成view对象的次数;即在创建view对象的时候,把所有孩子全部找到,并把孩子的引用给存起来
    ①定义存储控件引用的类ViewHolder
    这里的ViewHolder类需要不需要定义成static,根据实际情况而定,如果item不是很多的话,可以使用,这样在初始化的时候,只加载一次,可以稍微得到一些优化
    不过,如果item过多的话,建议不要使用。因为static是Java中的一个关键字,当用它来修饰成员变量时,那么该变量就属于该类,而不是该类的实例。所以用static修饰的变量,它的生命周期是很长的,如果用它来引用一些资源耗费过多的实例(比如Context的情况最多),这时就要尽量避免使用了。
    static class ViewHolder{
    //定义item中相应的控件
    }
    ②创建自定义的类:ViewHolder holder = null;
    ③将子view添加到holder中:
    在创建新的listView的时候,创建新的ViewHolder,把所有孩子全部找到,并把孩子的引用给存起来
    通过view.setTag(holder)将引用设置到view中
    通过holder,将孩子view设置到此holder中,从而减少以后查询的次数
    ④在复用listView中的条目的时候,通过view.getTag(),将view对象转化为holder,即转化成相应的引用,方便在下次使用的时候存入集合。
    通过view.getTag(holder)获取引用(需要强转)

    static class ViewHolder {
    TextView text;
    ImageView icon;
    }
    
    public View getView(int pos, View convertView, ViewGroup parent){
    ViewHolder holder;
    if (convertView == null) {
    convertView = mInflater.inflate(R.layout.list_item, null);
    holder = new ViewHolder();
    holder.text = (TextView) convertView.findViewById(
    R.id.text));
    holder.icon = (ImageView) convertView.findViewButId(
    R.id.icon));
    convertView.setTag(holder);
    } else {
    holder = (ViewHolder) convertView.getTag();
    }
    holder.text.setText(DATA[pos]);
    holder.icon.setImageBitmap((pos & 1) == 1 ? mIcon1 : mIcon2);
    return convertView;
    }

    二、ListView中数据的分批及分页加载:

    需求:ListView有一万条数据,如何显示;如果将十万条数据加载到内存,很消耗内存
    解决办法:
    优化查询的数据:先获取几条数据显示到界面上
    进行分批处理—优化了用户体验
    进行分页处理—优化了内存空间
    说明:
    一般数据都是从数据库中获取的,实现分批(分页)加载数据,就需要在对应的DAO中有相应的分批(分页)获取数据的方法,如findPartDatas ()
    1、准备数据:
    在dao中添加分批加载数据的方法:findPartDatas ()
    在适配数据的时候,先加载第一批的数据,需要加载第二批的时候,设置监听检测何时加载第二批
    2、设置ListView的滚动监听器:setOnScrollListener(new OnScrollListener{….})
    ①、在监听器中有两个方法:滚动状态发生变化的方法(onScrollStateChanged)和listView被滚动时调用的方法(onScroll)
    ②、在滚动状态发生改变的方法中,有三种状态:
    手指按下移动的状态: SCROLL_STATE_TOUCH_SCROLL: // 触摸滑动
    惯性滚动(滑翔(flgin)状态): SCROLL_STATE_FLING: // 滑翔
    静止状态: SCROLL_STATE_IDLE: // 静止
    3、对不同的状态进行处理:
    分批加载数据,只关心静止状态:关心最后一个可见的条目,如果最后一个可见条目就是数据适配器(集合)里的最后一个,此时可加载更多的数据。在每次加载的时候,计算出滚动的数量,当滚动的数量大于等于总数量的时候,可以提示用户无更多数据了。

    三、ListView中图片的优化:详看OOM异常中图片的优化

    1、处理图片的方式:
    如果自定义Item中有涉及到图片等等的,一定要狠狠的处理图片,图片占的内存是ListView项中最恶心的,处理图片的方法大致有以下几种:
    ①、不要直接拿路径就去循环decodeFile();使用Option保存图片大小、不要加载图片到内存去
    ②、拿到的图片一定要经过边界压缩
    ③、在ListView中取图片时也不要直接拿个路径去取图片,而是以WeakReference(使用WeakReference代替强引用。
    比如可以使用WeakReference mContextRef)、SoftReference、WeakHashMap等的来存储图片信息,是图片信息不是图片哦!
    ④、在getView中做图片转换时,产生的中间变量一定及时释放
    2、异步加载图片基本思想:
    1)、 先从内存缓存中获取图片显示(内存缓冲)
    2)、获取不到的话从SD卡里获取(SD卡缓冲)
    3)、都获取不到的话从网络下载图片并保存到SD卡同时加入内存并显示(视情况看是否要显示)
    原理:
    优化一:先从内存中加载,没有则开启线程从SD卡或网络中获取,这里注意从SD卡获取图片是放在子线程里执行的,否则快速滑屏的话会不够流畅。
    优化二:与此同时,在adapter里有个busy变量,表示listview是否处于滑动状态,如果是滑动状态则仅从内存中获取图片,没有的话无需再开启线程去外存或网络获取图片。
    优化三:ImageLoader里的线程使用了线程池,从而避免了过多线程频繁创建和销毁,有的童鞋每次总是new一个线程去执行这是非常不可取的,好一点的用的AsyncTask类,其实内部也是用到了线程池。在从网络获取图片时,先是将其保存到sd卡,然后再加载到内存,这么做的好处是在加载到内存时可以做个压缩处理,以减少图片所占内存。
    Tips:这里可能出现图片乱跳(错位)的问题:
    图片错位问题的本质源于我们的listview使用了缓存convertView,假设一种场景,一个listview一屏显示九个item,那么在拉出第十个item的时候,事实上该item是重复使用了第一个item,也就是说在第一个item从网络中下载图片并最终要显示的时候,其实该item已经不在当前显示区域内了,此时显示的后果将可能在第十个item上输出图像,这就导致了图片错位的问题。所以解决之道在于可见则显示,不可见则不显示。在ImageLoader里有个imageViews的map对象,就是用于保存当前显示区域图像对应的url集,在显示前判断处理一下即可。

    四、ListView的其他优化:

    1、尽量避免在BaseAdapter中使用static 来定义全局静态变量:
    static是Java中的一个关键字,当用它来修饰成员变量时,那么该变量就属于该类,而不是该类的实例。所以用static修饰的变量,它的生命周期是很长的,如果用它来引用一些资源耗费过多的实例(比如Context的情况最多),这时就要尽量避免使用了。
    2、尽量使用getApplicationContext:
    如果为了满足需求下必须使用Context的话:Context尽量使用Application Context,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题
    3、尽量避免在ListView适配器中使用线程:
    因为线程产生内存泄露的主要原因在于线程生命周期的不可控制。之前使用的自定义ListView中适配数据时使用AsyncTask自行开启线程的,这个比用Thread更危险,因为Thread只有在run函数不结束时才出现这种内存泄露问题,然而AsyncTask内部的实现机制是运用了线程执行池(ThreadPoolExcutor),这个类产生的Thread对象的生命周期是不确定的,是应用程序无法控制的,因此如果AsyncTask作为Activity的内部类,就更容易出现内存泄露的问题。解决办法如下:
    ①、将线程的内部类,改为静态内部类。
    ②、在线程内部采用弱引用保存Context引用

    欢迎大家关注我的个人微信公众号AndroidSharer,分享软件开发相关技术包括Android、Java Web、HTML5以及产品研发干货,偶尔喝点鸡汤
    这里写图片描述

    展开全文
  • 项目优化方案

    千次阅读 2012-12-29 10:00:43
    1.程序开发优化 1.循代码编写约定及规范 1.2基础代码优化 1.2.1字符串优化 1.2.1.1使用StringBuffter代替String 例如: String s ="a"+"b"+"c"+"d"+"..."; 替换为: StringBuffer sb= new ...
  • 数据库SQL优化大总结之 百万级数据库优化方案

    万次阅读 多人点赞 2016-06-23 09:43:50
    网上关于SQL优化的教程很多,但是比较杂乱。近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充。 这篇文章我花费了大量的时间查找资料、修改、排版,希望大家阅读之后,感觉好的...
  • 浅谈Android性能优化方案

    千次阅读 2016-01-06 19:06:55
    经过前一阶段的调查,大概对性能优化已经有了初步的解决方案:  先给大家介绍一下性能优化指标以及部分方案:  一、性能优化六项指标:  性能、内存、稳定性、流量、电量、安装包大小;  二、背景 ---- ...
  • sql优化问题(百万级数据优化方案)   一.sql数据库优化方案 1、索引 2、分库分表分区 3、数据库引擎  4、预处理  5、读写分离 1、索引,建立索引是数据库优化各种方案之中成本最低,见效最快的解决方案,...
  • Android App 性能优化方案

    千次阅读 2016-06-22 09:16:45
    1. 为什么需要性能优化? 上面说到,在时间窗口期内开发出产品是极端重要的,但是虽然基本功能我们实现了,但是开发出来的产品代码运行的效率怎么样呢?我们的App用户给用户的体验如何呢? 我们的App在低端机上...
  • SEO整站优化方案制作

    千次阅读 2018-08-15 13:53:41
    SEO整站优化方案制作 不管是我们为自己的网站SEO还是给自己公司的网站优化,又或者是给客户提供SEO服务,在SEO工作开始之前做好一份详细的SEO方案,不要怕费时间,只有有计划地去工作,才能让效率大大地提高。 ...
  • 越权问题解决优化方案

    万次阅读 2017-12-29 10:47:32
    把这种越权问题,作为整块测试任务来。新建自动化测试Case,让每一个接口(尤其是涉及分级的接口)都要有多个不同级别的用户进行权限校验。根据断言和数据库一致性(必须,有时候接口返回的成功,并不一定是成功)...
  • 做好ASO优化方案,步骤。

    千次阅读 2016-11-08 16:45:39
    ASO 优化现在是可以使用竞品的名称作为关键词的,一般放在关键词里是比较稳妥的,对于ASO优化--AppStore关键词排名优化规则,希望对做产品的ASO 优化能有所帮助 ASO优化--AppStore关键词排名优化规则 对产品而...
  • mysql 百万级数据库优化方案

    千次阅读 2018-06-21 14:26:45
    https://blog.csdn.net/Kaitiren/article/details/80307828一、百万级数据库优化方案1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。2.应尽量避免在 where 子句中对...
  • Android应用优化方案

    万次阅读 2016-11-21 00:10:45
    1. 为什么需要性能优化? 上面说到,在时间窗口期内开发出产品是极端重要的,但是虽然基本功能我们实现了,但是开发出来的产品代码运行的效率怎么样呢?我们的App用户给用户的体验如何呢? 我们的App在低端机上...
  • 网站SEO优化方案 全面详细的写法

    万次阅读 2018-02-26 13:46:27
    不管是我们为自己的网站SEO优化,还是公司网站的SEO优化,又或者是给客户提供SEO服务,小编都希望大家能在SEO工作开始之前做好一份详细的SEO方案,不要怕费时间,只有有计划地去工作,才能让效率大大地提高,...
  • 浅谈移动端页面性能优化方案

    千次阅读 2019-06-11 12:04:29
    这就要求我们产品质量越来越高,那对于我们前端工程师来说也是一个挑战,如何让我们所开发的页面能有更好的体验,就是我们今天讨论的话题:移动端页面性能优化。 Html5的出现对于移动端影响挺大,HTML5框架可以提升...
  • 详解MySQL大表优化方案

    千次阅读 2016-08-04 18:00:53
    当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化:单表优化、字段、索引、查询SQL、引擎等。
  • Webview优化方案之“去啊”极致方案

    千次阅读 2016-09-13 14:13:13
    今天在百度寻找一个合适的webview优化方案过程中,看到了这篇文章,分享给大家看看,希望对开发设计有一个好的影响。 原文地址:点击打开链接 去年(2015)四月份,我在 QCon 北京大会上分享了阿里旅行 Hybrid 实战...
  • 一个网站完整的SEO优化方案

    千次阅读 2016-03-23 16:48:15
    一个完整的SEO优化方案主要由四个小组组成: 一、前端/页编人员 二、内容编辑人员 三、推广人员 四、数据分析人员 接下来,我们就对这四个小组分配工作。 首先,前端/页编人员主要负责站内优化,主要从四个...
  • web移动端页面性能优化方案

    万次阅读 2017-05-01 10:12:48
    这就要求我们产品质量越来越高,那对于我们前端工程师来说也是一个挑战,如何让我们所开发的页面能有更好的体验,就是我们今天讨论的话题:移动端页面性能优化。 Html5的出现对于移动端影响挺大,HTML5框架可以...
  • 报表性能优化方案之报表取数

    千次阅读 2015-09-21 10:31:33
    1. 取数原理 设计器拼出最终的SQL,将SQL语句传给...下面是一些优化的方法。 2. 优化SQL FineReport报表的数据集采用的是表模型,也就是说通过SQL这种DSL语言,从数据库通过简单查询或各种组合关联查询
  • 一个完整的SEO优化方案

    千次阅读 2015-02-03 13:47:00
    一个完整的SEO优化方案主要由四个小组组成: 一、前端/页编人员 二、内容编辑人员 三、推广人员 四、数据分析人员 接下来,我们就对这四个小组分配工作。 首先,前端/页编人员主要负责站内优化,主要从四个...
  • PhoneGap优化解决方案

    千次阅读 2012-05-28 21:49:09
    在纵论PhoneGap一文中对PhoneGap和类似的跨平台技术了简单的介绍,本文继续介绍PhoneGap的技术细节吧。PhoneGap是开源的,大家可以去官网下载源码自己来研究,下面只是简单分析一下它的实现原理。 首先大家会...
  • Web交互设计优化方案+check list

    千次阅读 2017-08-03 09:58:52
    优化已有产品的体验”这是用户体验相关岗位职责中常见的描述。我们的产品常常是在快速的迭代过程中不断完善的,就像孩子生下来需要养育才能长大一样,优化已有功能/产品,和设计新功能/产品同样重要,不可偏废。 ...
  • postgreSQL单表数据量上千万分页查询缓慢的优化方案

    千次阅读 多人点赞 2019-12-26 17:03:08
    postgreSQL单表数据量上千万分页查询缓慢的优化方案
  • Lua配置表存储优化方案

    千次阅读 2017-01-15 14:07:38
    如何有效利用有限的硬件条件,实现当前高品质、高规格的游戏产品是持久不变的话题。 Lua作为一个极为精简的嵌入型脚本语言,已经广泛地用在了游戏业,Lua的存在一般是两种场合,一种用于实现游戏上层业务逻辑,一种...
  • 多请求多数据量综合页面优化方案

    千次阅读 2018-01-25 19:24:06
    关于页面优化一直是一个让...之前了一个综合展示页面,这个页面布局就想一个桌子,上面摆满了,水果,青菜,大鱼大肉,还有碗筷刀叉,总之东西很多,所以页面显示很慢。打开页面会有10s左右的卡死状态。老大让我解决

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 253,207
精华内容 101,282
关键字:

如何做产品优化方案