精华内容
下载资源
问答
  • 优化工作报告怎么写
    千次阅读
    2022-04-14 10:27:36

    目录

    一、压缩css、js文件

    二、css图标采用精灵图

    三、 CSS放在页面最上部,javascript放在页面最下面

    四、css选择器优化

    五、避免使用css表达式

    六、js中避免使用eval

    七、减少闭包的使用

     八、绑定DOM元素时使用采用事件委托

     九、尽量使用css动画来代替js动画

    十、少使用id选择器,多使用类选择器

    十一、图片采用懒加载技术 


    一、压缩css、js文件

    在做项目的过程中,最好把css或者js文件合并或者是压缩,特别是在开发移动端得时候,如果css或者js内容不是很多,我们可以采用内嵌式,来减少http的请求的次数,加快页面加载速度。如果样式有很多的话,建议采用以下方法进行优化。

    1. 尽量把css和js文件压缩成一个文件,来减少http请求次数
    2. 使用webpack把文件压缩成min.js等包来减少文件大小
    3. 通过一些自动化工具完成css以及js的合并压缩,或者再完成less转css,es6转es5等操作,我们这种自动化构建模式,称之为前端“工程化”开发
    4. 使用服务器开启资源文件的GZIP压缩

    二、css图标采用精灵图

    就是将很多小图片合并成一个大图片,通过定位的方式将图片定位到所需位置上。

    通过background-size: 0 0来对图片大小保持一致,用background-position来对图片位置具体定位

    三、 CSS放在页面最上部,javascript放在页面最下面

            浏览器会在下载完成全部CSS之后才对整个页面进行渲染,因此最好的做法是将CSS放在页面最上面,让浏览器尽快下载CSS。如果将 CSS放在其他地方比如 BODY中,则浏览器有可能还未下载和解析到 CSS就已经开始渲染页面了,这就导致页面由无 CSS状态跳转到 CSS状态,用户体验比较糟糕,所以可以考虑将CSS放在HEAD中。
            Javascript则相反,浏览器在加载javascript后立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此javascript最好放在页面最下面。但如果页面解析时就需要用到javascript,这时放到底部就不合适了。

    最好css放在head中,js放在body尾部,让页面加载的时候,先加载css,再加载js(先呈现页面,再给用户提供操作)

    四、css选择器优化

    • 尽量减少标签选择器的使用
    • 尽量少使用id选择器,多使用样式类选择器(通用性比较强)
    • 减少选择器前面的前缀(选择器是从右向左查找的,前缀多,查询的时间多)

    五、避免使用css表达式

    css如果需要写表达式最好通过js去实现 

    六、js中避免使用eval

    使用eval的坏处就是性能消耗大、代码压缩后,容易出现代码执行报错等问题。

    七、减少闭包的使用

    因为闭包会形成一个不会消失的栈内存,过多的栈内存会导致页面的性能变得卡顿,并且还会容易造成内存的泄漏,但是闭包还是有很多好处的,只是建议尽量少用。

     八、绑定DOM元素时使用采用事件委托

    把事件绑定给外层容器,当里面的后代元素相关行为被触发,外层容器绑定的方法也会被触发执行(冒泡传播机制导致)通过事件源是谁,然后对其做不同的操作即可

     九、尽量使用css动画来代替js动画

    css3的动画或者变形,性能比js动画好。

    十、少使用id选择器,多使用类选择器

    十一、图片采用懒加载技术 

    在实际项目中,我们开始图片都不进行加载,页面首次加载完成后,先把第一屏幕中可以看见的图片进行加载,随着页面滚动,再把下面区域中能够呈现出来的图片进行加载。

    详情见JavaScript——懒加载_Nanchen_42的博客-CSDN博客_javascript 懒加载

    更多相关内容
  • xxx市工业和信息化局优化营商环境工作开展情况报告.docx
  • 多多益处(提升团队协作,以及工程运维,避免人工处理琐碎而重复的工作) 模块化开发 将前端性能优化理论落地,代码压缩,合并,缓存控制,提取公共代码等 其他的还包括比如你可以用ES 6 或CoffeeScript源码,...
  • 性能优化一般包含:数据聚合优化、资源冲突优化、算法优化、JVM优化、复用优化、计算优化和快速优化,冰河吐血整理,建议大家收藏!!

    大家好,我是冰河~~

    随着互联网的高速发展,互联网行业已经从IT时代慢慢步入到DT时代。对于Java程序员的要求越来越高,只是单纯的掌握CRUD以不足以胜任互联网公司的相关职位,大量招聘岗位显示:如果是面试中高级的Java岗,基本上都需要懂性能优化的相关知识。今天,我们就一起来聊聊如何进行性能优化这个话题。

    小伙伴们如果觉得文章不错,点赞、收藏、评论,分享走一起呀,记得给冰河来个一键三连~~

    好了,我们开始今天的正文。

    性能优化有哪些方面?

    这里,我结合平时工作中的总结,将性能优化总结为下面这张图。

    在这里插入图片描述

    也就是说,我们可以从数据聚合优化、资源冲突优化、算法优化、JVM优化、复用优化、计算优化和快速实现等方面来进行回答。接下来,我们就针对每个点进行说明。

    数据聚合优化

    数据聚合优化主要针对的是对于数据的整合和传输的优化。比如:我们从数据库中查询出的数据,经过程序的聚合处理后再返回给客户端,而不用客户端调用多次接口来分别获取数据。

    再比如:我们在项目中使用的Nginx,一般都会开启GZIP压缩,使传输的数据更加紧凑,同时,使传输的数据量更小。

    细心的小伙伴会发现,我们对于数据聚合的优化,主要是使传输的数据量更小。所以,我们在使用SQL语句查询数据库中的数据时,尽量查询那些需要的字段,对于不需要的字段就直接忽略不查询了,避免在SQL语句中出现select *

    资源冲突优化

    在我们平时的工作中,尤其是在高并发的场景下,经常会出现锁冲突的问题,锁冲突是资源冲突的一个典型场景。

    关于锁我们可以联想到数据库的行锁、表锁、Java中的synchronized和Lock等。如果对应到操作系统级别,则会有CPU命令级别的锁,JVM指令级别的锁,操作系统的内部锁等。

    这里,小伙伴们需要注意一点:只有在并发的场景下,才会出现资源冲突的问题。也就是说:在同一时刻,只能有一个请求获取到请求资源,解决冲突的方式就是加锁。

    我们需要在平时的工作过程中避免锁冲突的问题,优化如何优化加锁方式,小伙伴们可以参见《【高并发】面试官:讲讲高并发场景下如何优化加锁方式?》一文。

    算法优化

    在一个大型的互联网项目中,往往涉及到分布式和微服务等技术,其中,也会使用到大量的数据结构和算法,对于算法的优化能够显著的提高系统的性能。一个好的实现,相比于一个拙劣的实现来说,在系统性能的提升上存在着巨大的差异。

    比如,作为 List 的实现,LinkedList 和 ArrayList 在随机访问的性能上,差了好几个数量级;又比如,CopyOnWriteList 采用写时复制的方式,可以显著降低读多写少场景下的锁冲突。而什么时候使用同步,什么时候是线程安全的,也对我们的编码能力有较高的要求。

    所以,我们需要在平时工作过程中,多多积累数据结构和算法的相关知识。

    JVM优化

    JVM调优,不用说,这是每个Java工程师必须要掌握的标准技能。所有的Java程序最终都是运行在JVM中的,对JVM进行优化也能够提升Java程序的性能。但是,需要注意的是:如果在优化JVM时,参数设置不当,可能会造成内存溢出等严重的问题。

    目前被广泛使用的垃圾回收器是 G1,通过很少的参数配置,内存即可高效回收。CMS 垃圾回收器已经在 Java 14 中被移除,由于它的 GC 时间不可控,有条件应该尽量避免使用。

    复用优化

    复用优化,这个看名字就知道,说白了就是可以重复利用。估计很多小伙伴都有这样的经验,在写代码的时候,可以将很多重复的代码抽象出来,做成公共的方法。这样,就不用每次都去写重复的逻辑代码了。这是代码层面的复用。

    如果是数据层面的话,我们可以使用缓冲和缓存来复用数据。

    这里,小伙伴们需要注意一个知识点:缓冲主要针对的是写操作,缓存主要针对的是读操作。

    另一个复用优化的典型场景就是池化技术,比如:数据库连接池、线程池等。

    计算优化

    对于计算优化来说,我们可以从以下几个小的方面来阐述。

    并行计算

    不难理解,就是多个计算同时进行。这里,又可以将并行计算分为:多机并行计算、多进程并行计算和多线程并行计算。

    多机并行计算: 将一个大的计算任务,拆分成N个小的计算任务,分发到不同的机器进行处理。典型的场景就是Hadoop的MapReduce极端。

    多进程计算: 比如,Nginx采用的NIO模型,采用的是进程调度的策略,由Master进程调度Worker进程,Worker进行来处理具体的请求。

    多线程计算: 对于多线程计算来说,也是我们平时接触最多的一种计算方式,我们可以使用多线程技术,将复杂的逻辑计算拆分成一个个小的计算任务,分发到不同的线程中去执行。

    同步变异步

    同步和异步的区别就是:同步需要等待返回结果,异步不需要等待返回结果。如果我们在业务程序中,不需要等待返回结果数据,则我们可以将同步调用优化为异步调用,从而提升我们系统的性能。

    懒加载

    最典型的场景就是Spring中的懒加载,只有第一次获取bean的时候,才会创建bean实例。

    快速实现

    对于快速实现来说,不仅包含我们需要利用相关的程序框架迅速开发出我们想要的业务,也需要我们在进行技术选型时,尽量使用一些性能优良的组件。比如,在进行网络开发时,尽量选择Netty,结合轻量级的数据传输,就不要使用WebService等技术了。

    很多公司喜欢使用适配器模式,在一些现有的开源组件之上,再抽象一层自己的组件,这样就能够做到切换底层组件的时候,对上层应用无感。

    写在最后

    如果你想进大厂,想升职加薪,或者对自己现有的工作比较迷茫,都可以私信我交流,希望我的一些经历能够帮助到大家~~

    推荐阅读:

    好了,今天就到这儿吧,小伙伴们点赞、收藏、评论,一键三连走起呀,我是冰河,我们下期见~~

    展开全文
  • MySQL索引优化总结

    千次阅读 2021-09-29 23:17:15
    本篇博客详细的介绍了索引优化的20个原则,只要在工作中能够随时应用到,相信你出的SQL能够命中索引,效率杠杠的。 一、索引的分类 1.1、普通索引、主键索引和唯一索引 1.2、聚集索引和非聚集索引 1.3、联合...

    前言:相信大家都知道索引可以大大提高MySQL的检索速度,但是真正在平时工作中写SQL,真的会考虑到这条SQL如何能够用上索引提升执行效率?本篇博客详细的介绍了索引优化的20个原则,只要在工作中能够随时应用到,相信你写出的SQL能够命中索引,效率杠杠的。

    一、索引的分类

    索引可以大大提高MySQL的检索速度。索引就像书中的目录一样为了让我们更快的寻找到自己想要的数据,下面是MySQL常用的索引简介。

     1.1、普通索引、主键索引和唯一索引

    (1) 普通索引

    这是最基本的索引,它没有任何限制。

    如何使用?

    //方式1
    ALTER TABLE table_name ADD INDEX index_name ( column )

    比如:ALTER TABLE users ADD INDEX index_users( id )

    //方式2
    CREATE INDEX index_name ON table_name (column_name)

    比如:CREATE INDEX index_users ON users (id)

    (2) 唯一索引

    与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须一。

    如何使用?

    //方式1
    ALTER TABLE table_name ADD UNIQUE [indexName] (column)

    比如:ALTER TABLE users ADD UNIQUE index_users( id )

    //方式2
    CREATE UNIQUE INDEX index_name ON table_name (column_name)

    比如:CREATE UNIQUE INDEX index_users ON users(id)

    (3) 主键索引

    它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候指定了主键,就会自动创建主键索引, CREATE INDEX不能用来创建主键索引,使用 ALTER TABLE来代替。

    如何使用?

    //方式1
    ALTER TABLE table_name ADD PRIMARY KEY ( column )

    比如:ALTER TABLE users ADD PRIMARY KEY ( id )

    方式2:创建表的时候指定主键

     1.2、聚集索引和非聚集索引

    (1)聚集索引

    聚集索引,又叫聚簇索引,所有的数据都存在聚集索引上,叶子节点直接对应数据,从中间级的索引页的索引行直接对应数据页。InnoDB存储引擎中的主键默认就会创建一个聚集索引,每张表只能创建一个聚集索引。记录的索引顺序与物理顺序相同,更适合between and和order by操作。

    InnoDB聚集索引的叶子节点存储行记录,因此, InnoDB必须要有,且只有一个聚集索引:

    (1)如果表定义了PK,则PK就是聚集索引;

    (2)如果表没有定义PK,则第一个not NULL unique列是聚集索引;

    (3)否则,InnoDB会创建一个隐藏的row-id作为聚集索引

    画外音:所以PK查询非常快,直接定位行记录。

    打个比方,一个表就像是我们以前用的新华字典,聚集索引就像是拼音目录,而每个字存放的页码就是我们的数据物理地址,我们如果要查询一个“哇”字,我们只需要查询“哇”字对应在新华字典拼音目录对应的页码,就可以查询到对应的“哇”字所在的位置,而拼音目录对应的A-Z的字顺序,和新华字典实际存储的字的顺序A-Z也是一样的,如果我们中文新出了一个字,拼音开头第一个是B,那么他插入的时候也要按照拼音目录顺序插入到A字的后面。

    (2)非聚集索引

    非聚集索引,又叫非聚簇索引、辅助索引,所有的数据和索引的目录是分开存的,叶子节点不存放具体的整行数据(叶子结点不直接指向数据页),而是存储的这一行的主键的值。

    记录的索引顺序与物理顺序无关。每张表可以有多个非聚集索引,需要更多磁盘和内存,多个索引会影响insert和update的速度。

    画外音:非聚集索引需要回表查询,先定位主键值,再定位行记录,因为要扫描两遍索引树,它的性能较扫一遍索引树更低。

    其实按照定义,除了聚集索引以外的索引都是非聚集索引,只是人们想细分一下非聚集索引,分成普通索引,唯一索引,全文索引。如果非要把非聚集索引类比成现实生活中的东西,那么非聚集索引就像新华字典的偏旁字典,他结构顺序与实际存放顺序不一定一致。

     1.3、联合索引最左匹配原则

    联合索引又叫复合索引,对表上的多个字段同时建立的索引(有顺序,ABC,ACB是完全不同的两种联合索引。)以联合索引(a,b,c)为例,建立这样的索引相当于建立了索引a、ab、abc三个索引。

    遵循最左前缀原则(必须带着最左边的列做条件才能命中索引),且从出现范围开始索引失效;

    当遇到范围查询(>、<、between、like)就会停止匹配。也就是:

    #这样a,b可以用到(a,b,c),c不可以
    select * from t where a=1 and b>1 and c =1;     

    这条语句只有 a,b 会用到索引,c 都不能用到索引。

    create index mix_ind on 表名 (id,name,email);
    
    select * from 表名 where id = 123;  # 命中索引
    
    select * from 表名 where id = 123 and name = 'pamela';  # 命中索引
    
    select * from 表名 where id > 123 and name = 'pamela';  # id命中,name不命中索引,因为出现范围
    
    select * from 表名 where id = 123 and email = 'pamela@123.com';  # 命中索引
    
    select * from 表名 where email = 'pamela@123.com';  # 不命中索引,因为条件中没有id
    
    select * from 表名 where name='pamela' and email = 'pamela@123.com';  # 不命中
    A:select * from student where age = 16 and name = '小张'
    
    B:select * from student where name = '小张' and sex = '男'
    
    C:select * from student where name = '小张' and sex = '男' and age = 18
    
    D:select * from student where age > 20 and name = '小张'
    
    E:select * from student where age != 15 and name = '小张'
    

     A遵从最左匹配原则,age是在最左边,所以A走索引;

     B直接从name开始,没有遵从最左匹配原则,所以不走索引;

     C虽然从name开始,但是有索引最左边的age,mysql内部会自动转成where age = '18' and name = '小张'  and sex = '男' 这种,所以还是遵从最左匹配原则;

     D这个是因为age>20是范围,范围字段会结束索引对范围后面索引字段的使用,所以只有走了age这个索引;

     E这个虽然遵循最左匹配原则,但是不走索引,因为!= 不走索引;

    question1:如何给下列sql语句加上联合索引?

    select * from test where a = 1 and b = 1 and c = 1;
    

    answer:

    咱们一看,直接加索引(a,b,c)就可以了,其实不然,也不能说这个答案不对,只能说这个答案不够完整。因为mysql在执行的时候会经历优化器过程,所以会把sql语句自动优化成符合索引的顺序,所以索引(a,b,c) (a,c,b) 或者是(c,b,a)都是可以的,那我们究竟如何确定索引呢?这个就得根据实际情况来了,比如a字段是表示性别的,只有0,1和2三个值来表示 未知,男,女三种性别,那么把a字段放在联合索引的最后会比较合适,反正哪个字段的内容重复率越高,就把哪个字段往联合索引的后面放。

    question2:如何给下列sql语句加上索引?

    SELECT * FROM table WHERE a > 1 and b = 2; 
    

    answer:

    如果咱们建立索引(a,b),那么a>1是可以走到索引的,但是b=2就没法走到索引了。但是如果咱们建立索引(b,a),那么sql语句会被自动优化成 where b=2 and a> 1,这样a和b都能走到索引,所以建立索引(b,a)比较合适

     1.4、索引覆盖和回表

    使用聚集索引(主键或第一个唯一索引)就不会回表,非聚集索引就会回表。当select的数据列被所建索引覆盖时不需要回表,可以直接取得数据。

    覆盖索引是select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。覆盖索引在查询过程中不需要回表。只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表速度更快。

    覆盖索引其核心就是只从辅助索引要数据。那么, 普通索引(单字段)和联合索引,以及唯一索引都能实现覆盖索引的作用。explain的输出结果Extra字段为Using index时,能够触发索引覆盖。

    create index ind_id on 表名(id);  # 对id字段创建了索引
    
    select id from 表名  where id > 100;  # 覆盖索引:在查找一条数据的时候,命中索引,不需要再回表 
    select max(id) from 表名  where id > 100;  # 覆盖索引:在查找一条数据的时候,命中索引,不需要再回表 
    select count(id) from 表名  where id > 100;  # 覆盖索引:在查找一条数据的时候,命中索引,不需要再回表 
    select name from 表名  where id > 100;  # 相对慢

    (1) 如何实现索引覆盖?

    常见的方法是:将被查询的字段,建立到联合索引里去。

    select id,name from user where name='shenjian';

     能够命中name索引,索引叶子节点存储了主键id,通过name的索引树即可获取id和name,无需回表,符合索引覆盖,效率较高。

    Extra:Using index。

    (2)哪些场景可以利用索引覆盖来优化SQL? 

    场景1:全表count查询优化

    原表为:user(PK id, name, sex);不能利用索引覆盖

    select count(name) from user;

    添加索引,就能够利用索引覆盖提效

    alter table user add key(name);

    场景2:列查询回表优化

    这个例子不再赘述,将单列索引(name)升级为联合索引(name, sex),即可避免回表。

    场景3:分页查询

    将单列索引(name)升级为联合索引(name, sex),也可以避免回表。

    1.5、前缀索引

    前缀索引说白了就是对文本的前几个字符(具体是几个字符在建立索引时指定)建立索引,这样建立起来的索引更小,所以查询更快。

    ALTER TABLE table_name ADD KEY(column_name(prefix_length));

    MySQL 前缀索引能有效减小索引文件的大小,提高索引的速度。但是前缀索引也有它的坏处:MySQL 不能在 ORDER BY 或 GROUP BY 中使用前缀索引,也不能把它们用作覆盖索引(Covering Index)。

     1.6、索引合并

    深入理解 index merge 是使用索引进行优化的重要基础之一。理解了 index merge 技术,我们才知道应该如何在表上建立索引。

    为什么会有index merge?

    我们的 where 中可能有多个条件(或者join)涉及到多个字段,它们之间进行 AND 或者 OR,那么此时就有可能会使用到 index merge 技术。index merge 技术如果简单的说,其实就是:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union)

    MySQL5.0之前,一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。但是从5.1开始,引入了 index merge 优化技术,对同一个表可以使用多个索引分别进行条件扫描。

    索引合并是指分别创建的两个索引,在某一次查询中临时合并成一条索引。

    # 索引合并
    create index ind_id on 表名(id);
    create index ind_email on 表名(email);
    
    select * from 表名 where id=100 or email = 'pamela@123.com'  # 索引合并,临时把两个索引ind_id和ind_email合并成一个索引

     1.7、索引下推

    (1)索引下推简介

    索引条件下推(Index Condition Pushdown),简称ICP。MySQL5.6新添加,用于优化数据的查询。 通过索引下推对于非主键索引进行优化,可有效减少回表次数,从而提高效率。

    如果没有索引下推优化(或称ICP优化),当进行索引查询时,首先根据索引来查找记录,然后再根据where条件来过滤记录;在支持ICP优化后,MySQL会在取出索引的同时,判断是否可以进行where条件过滤再进行索引查询,也就是说提前执行where的部分过滤操作,在某些场景下,可以大大减少回表次数,从而提升整体性能。

    • 当你不使用ICP,通过使用非主键索引(普通索引or二级索引)进行查询,存储引擎通过索引检索数据,然后返回给MySQL服务器,服务器再判断是否符合条件。

    • 使用ICP,当存在索引的列做为判断条件时,MySQL服务器将这一部分判断条件传递给存储引擎,然后存储引擎通过判断索引是否符合MySQL服务器传递的条件,只有当索引符合条件时才会将数据检索出来返回给MySQL服务器。

    (2)适用场景

    • 当需要整表扫描,e.g.:range,ref,eq_ref....

    • 适用InnoDB引擎和MyISAM引擎查询(5.6版本不适用分区查询,5.7版本可以用于分区表查询)。

    • InnoDB引擎仅仅适用二级索引。(原因InnoDB聚簇索引将整行数据读到InnoDB缓冲区)。

    • 子查询条件不能下推。触发条件不能下推,调用存储过程条件不能下推。


    二、索引优化规则

    查询的条件字段尽量用索引字段

    2.0、and/or条件相连

    and条件相连,有一列有索引就会命中索引,加快查询速度;or条件相连,所有列都有索引才能命中索引,加快查询速度;

    create index mix_ind on 表名 (id);
    
    select * from 表名 where id = 123 and name = 'pamela';  # 有一列有索引,速度快
    
    select * from 表名 where id = 123 or name = 'pamela';  # 不是所有列都有索引,速度慢

    2.1、like语句的前导模糊查询不能使用索引

    select * from doc where title like '%XX';   --不能使用索引
    
    select * from doc where title like 'XX%';   --非前导模糊查询,可以使用索引

    因为页面搜索严禁左模糊或者全模糊,如果需要可以使用搜索引擎来解决。

    2.2、union、in、or 都能够命中索引,建议使用 in

    union能够命中索引,并且MySQL 耗费的 CPU 最少。

    select * from doc where status=1
    
    union all
    
    select * from doc where status=2;

    in能够命中索引,查询优化耗费的 CPU 比 union all 多,但可以忽略不计,一般情况下建议使用 in。

    select * from doc where status in (1, 2);

    or 新版的 MySQL(MySQL5.0后) 索引合并能够命中索引,查询优化耗费的 CPU 比 in多,不建议频繁用or。

    select * from doc where status = 1 or status = 2

    补充:有些地方说在where条件中使用or,索引会失效,造成全表扫描,这是个误区:

    • 要求where子句使用的所有字段,都必须建立索引;

    • 如果数据量太少,mysql制定执行计划时发现全表扫描比索引查找更快,所以会不使用索引;

    • 确保mysql版本5.0以上,且查询优化器开启了index_merge_union=on, 也就是变量optimizer_switch里存在index_merge_union且为on。

    2.3、负向条件查询不能使用索引

    负向条件有:!=、<>、not in、not exists、not like 等。

    例如下面SQL语句:

    select * from doc where status != 1 and status != 2;

    可以优化为 in 查询:

    select * from doc where status in (0,3,4);

    2.4、联合索引最左前缀原则

    如果在(a,b,c)三个字段上建立联合索引,那么他会自动建立 a| (a,b) | (a,b,c)组索引。联合索引遵循最左前缀原则(必须带着最左边的列做条件才能命中索引),且从出现范围开始索引失效;

    
    create index mix_ind on 表名 (id,name,email);
    
    select * from 表名 where id = 123;  # 命中索引
    
    select * from 表名 where id > 123;  # 不命中索引,因为出现范围
    
    select * from 表名 where id = 123 and name = 'pamela';  # 命中索引
    
    select * from 表名 where id > 123 and name = 'pamela';  # 不命中索引,因为出现范围
    
    select * from 表名 where id = 123 and email = 'pamela@123.com';  # 命中索引
    
    select * from 表名 where email = 'pamela@123.com';  # 不命中索引,因为条件中没有id
    
    select * from 表名 where name='pamela' and email = 'pamela@123.com';  # 不命中索引,因为条件中没有id

    登录业务需求,SQL语句如下:

    select uid, login_time from user where login_name=? andpasswd=?

    可以建立(login_name, passwd)的联合索引。因为业务上几乎没有passwd 的单条件查询需求,而有很多login_name 的单条件查询需求,所以可以建立(login_name, passwd)的联合索引,而不是(passwd, login_name)。

    2.5、不能使用索引中范围条件右边的列(范围列可以用到索引),范围列之后列的索引全失效。

    范围条件有:<、<=、>、>=、between等。

    索引最多用于一个范围列,如果查询条件中有两个范围列则无法全用到索引。

    假如有联合索引 (empno、title、fromdate),那么下面的 SQL 中 emp_no 可以用到索引,而title 和 from_date 则使用不到索引。

    select * from employees.titles where emp_no < 10010' and title='Senior Engineer'and from_date between '1986-01-01' and '1986-12-31'

    2.6、不要在索引列上面做任何操作(计算、函数),否则会导致索引失效而转向全表扫描。

    例如下面的 SQL 语句,即使 date 上建立了索引,也会全表扫描:

    select * from doc where YEAR(create_time) <= '2016';

    可优化为值计算,如下:

    select * from doc where create_time <= '2016-01-01';

    比如下面的 SQL 语句:

    select * from order where date < = CURDATE();

    可以优化为:

    select * from order where date < = '2018-01-2412:00:00';

    2.7、强制类型转换会全表扫描

    字符串类型不加单引号会导致索引失效,因为mysql会自己做类型转换,相当于在索引列上进行了操作。

    如果 phone 字段是 varchar 类型,则下面的 SQL 不能命中索引。

    select * from user where phone=13800001234

    可以优化为:

    select * from user where phone='13800001234';

    2.8、更新十分频繁、数据区分度不高的列不宜建立索引

    更新会变更 B+ 树,更新频繁的字段建立索引会大大降低数据库性能。

    “性别”这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类似。

    一般区分度在80%以上的时候就可以建立索引,区分度可以使用 count(distinct(列名))/count(*) 来计算。

    2.9、利用覆盖索引来进行查询操作,避免回表,减少select * 的使用

    覆盖索引:查询的列和所建立的索引的列个数相同,字段相同。

    被查询的列,数据能从索引中取得,而不用通过行定位符 row-locator 再到 row 上获取,即“被查询列要被所建的索引覆盖”,这能够加速查询速度。

    例如登录业务需求,SQL语句如下。

    select uid, login_time from user where login_name=? and passwd=?

    可以建立(login_name, passwd, login_time)的联合索引,由于 login_time 已经建立在索引中了,被查询的 uid 和 login_time 就不用去 row 上获取数据了,从而加速查询。

    2.10、索引不会包含有NULL值的列

    只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时,尽量使用not null 约束以及默认值。

    2.11、is null, is not null无法使用索引

    2.12、如果有order by、group by的场景,请注意利用索引的有序性

    order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort 的情况,影响查询性能。

    例如对于语句 where a=? and b=? order by c,可以建立联合索引(a,b,c)。

    如果索引中有范围查找,那么索引有序性无法利用,如 WHERE a>10 ORDER BY b;,索引(a,b)无法排序。

    2.13、使用短索引(前缀索引)

    对列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果该列在前10个或20个字符内,可以做到既使得前缀索引的区分度接近全列索引,那么就不要对整个列进行索引。因为短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作,减少索引文件的维护开销。可以使用count(distinct leftIndex(列名, 索引长度))/count(*) 来计算前缀索引的区分度。

    但缺点是不能用于 ORDER BY 和 GROUP BY 操作,也不能用于覆盖索引。

    不过很多时候没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。

    2.14、利用延迟关联或者子查询优化超多分页场景

    MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。

    示例如下,先快速定位需要获取的id段,然后再关联:

    select a.* from 表1 a,(select id from 表1 where 条件 limit100000,20 ) b where a.id=b.id;

    2.15、如果明确知道只有一条结果返回,limit 1 能够提高效率

    比如如下 SQL 语句:

    select * from user where login_name=?;

    可以优化为:

    select * from user where login_name=? limit 1

    自己明确知道只有一条结果,但数据库并不知道,明确告诉它,让它主动停止游标移动。

    2.16、超过三个表最好不要 join

    需要 join 的字段,数据类型必须一致,多表关联查询时,保证被关联的字段需要有索引。

    例如:left join是由左边决定的,左边的数据一定都有,所以右边是我们的关键点,建立索引要建右边的。当然如果索引在左边,可以用right join。

    2.17、单表索引建议控制在5个以内

    2.18、SQL 性能优化 explain 中的 type:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好

    consts:单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。

    ref:使用普通的索引(Normal Index)。

    range:对索引进行范围检索。

    当 type=index 时,索引物理文件全扫,速度非常慢。

    2.19、业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引

    不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的。另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。

    2.20、创建索引时避免以下错误观念

    索引越多越好,认为需要一个查询就建一个索引。宁缺勿滥,因为索引会消耗空间、严重拖慢更新和新增速度。

    抵制惟一索引,认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。

    过早优化,在不了解系统的情况下就开始优化。


    三、使用索引和不使用索引的情况

    3.1、使用索引

    • 主键自动建立唯一索引。 

    • 经常作为查询条件在WHERE或者ORDER BY 语句中出现的列要建立索引。 

    • 查询中与其他表关联的字段,外键关系建立索引。 

    • 经常用于聚合函数的列要建立索引,如min(),max()等的聚合函数。

    3.2、不使用索引

    • 经常增删改的列不要建立索引。 

    • 有大量重复的列不建立索引。 

    • 表记录太少不要建立索引,因为数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果 。


    参考链接:

    MySQL索引连环18问

    聚集索引与非聚集索引的总结

    MySQL 优化之 index merge(索引合并)

    mysql覆盖索引与回表

    MySQL之 索引下推

    什么是数据库索引

    展开全文
  • Blackfin C语言优化

    2021-01-19 22:43:49
    不过这一段日子总是有一种冲动想要点什么,把自己了解的有关Blackfin C语言优化和系统优化方面的技巧和知识下来,和正在从事这方面工作朋友们分享,也许有些帮助,也算是对自己过去一段时间工作总结。...
  • 如何出高性能代码(三)优化内存回收(GC)

    千次阅读 多人点赞 2022-05-02 09:33:33
      本文是《如何出高性能代码》系列的第三篇,本文将告诉你如何出GC更优的代码,以达到提升代码性能的目的 优化内存回收   垃圾回收GC(Garbage Collection)是现在高级编程语言内存回收的主要手段,也是高级...

    导语

      同一份逻辑,不同人的实现的代码性能会出现数量级的差异; 同一份代码,你可能微调几个字符或者某行代码的顺序,就会有数倍的性能提升;同一份代码,也可能在不同处理器上运行也会有几倍的性能差异;十倍程序员 不是只存在于传说中,可能在我们的周围也比比皆是。十倍体现在程序员的方法面面,而代码性能却是其中最直观的一面。
      本文是《如何写出高性能代码》系列的第三篇,本文将告诉你如何写出GC更优的代码,以达到提升代码性能的目的

    优化内存回收

      垃圾回收GC(Garbage Collection)是现在高级编程语言内存回收的主要手段,也是高级语言所必备的特性,比如大家所熟知的Java、python、go都是自带GC的,甚至是连C++ 也开始有了GC的影子。GC可以自动清理掉那些不用的垃圾对象,释放内存空间,这个特性对新手程序猿极其友好,反观没有GC机制的语言,比如C++,程序猿需要自己去管理和释放内存,很容易出现内存泄露的bug,这也是C++的上手难度远高于很多语言的原因之一。
      GC的出现降低了编程语言上手的难度,但是过度依赖于GC也会影响你程序的性能。这里就不得不提到一个臭名昭著的词——STW(stop the world) ,它的含义就是应用进程暂停所有的工作,把时间都让出来让给GC线程去清理垃圾。别小看这个STW,如果时间过长,会明显影响到用户体验。像我之前从事的广告业务,有研究表明广告系统响应时间越长,广告点击量越低,也就意味着挣到的钱越少。
      GC还有个关键的性能指标——吞吐率(Throughput),它的定义是运行用户代码的时间占总CPU运行时间的比例。举个例子,假设吞吐率是60%,意味着有60%的CPU时间是运行用户代码的,而剩下的40%的CPU时间是被GC占用。从其定义来看,当然是吞吐率越高越好,那么如何提升应用的GC吞吐率呢? 这里我总结了三条。

    减少对象数量

      这个很好理解了,产生的垃圾对象越少,需要的GC次数也就越少。那如何能减少对象的数量?这就不得不回顾下我们在上一讲巧用数据特性 中提到的两个特性——可复用性和非必要性,忘记的同学可以再点开上面的链接回顾下。这里再大概讲下这两个特性是如何减少对象生成的。

    可复用性

      可复用性在这里指的是,大多数的对象都是可以被复用的,这些可以被复用的对象就没必要每次都新建出来,浪费内存空间了。 处了巧用数据特性 中的例子,我这里再个Java中已经被用到的例子,这个还得从一段奇怪的代码说起。

    Integer i1 = Integer.valueOf(111);
    Integer i2 = Integer.valueOf(111);
    System.out.println(i1 == i2);
    
    Integer i3 = Integer.valueOf(222);
    Integer i4 = Integer.valueOf(222);
    System.out.println(i3 == i4);
    

      
      上面这段代码的输出结果会是啥呢?你以为是true+true,实际上是true+false。 What?? Java中222不等于222,难道是有Bug? 其实这是新手在比较数值大小时常犯的一个错误,包装类型间的相等判断应该用equals而不是’’,'’只会判断这两个对象是否是同一个对象,而不是对象中包的具体值是否相等。
     在这里插入图片描述
      像1、2、3、4……等一批数字,在任何场景下都是非常常用的,如果每次使用都新建个对象很是浪费,Java的开发者也考虑到了这点,所以在Jdk中提取缓存了一批整数的对象(-128到127),这些数字每次都可以直接拿过来用,而不是新建一个对象出来。而在-128到127范围外的数字,每次都会是新对象,下面是Integer.valueOf()的源码及注释:

    /**
         * Returns an {@code Integer} instance representing the specified
         * {@code int} value.  If a new {@code Integer} instance is not
         * required, this method should generally be used in preference to
         * the constructor {@link #Integer(int)}, as this method is likely
         * to yield significantly better space and time performance by
         * caching frequently requested values.
         *
         * This method will always cache values in the range -128 to 127,
         * inclusive, and may cache other values outside of this range.
         * 
         * @param  i an {@code int} value.
         * @return an {@code Integer} instance representing {@code i}.
         * @since  1.5
         */
        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
    

      我在Idea中通过Debug看到了i1-i4几个对象,其实111的两个对象确实是同一个,而222的两个对象确实不同,这就解释了上面代码中的诡异现象。

    非必要性

      非必要性的意思是有些对象可能没必要生成。这里我举个例子,可能类似下面这种代码,在业务系统中会很常见。

        private List<UserInfo> getUserInfos(List<String> ids) {
            List<UserInfo> res = new ArrayList<>(ids.size());
            if (ids == null || res.size() == 0) {
                return new Collections.emptyList();
            }
            List<UserInfo> validUsers = ids.stream()
                    .filter(id -> isValid(id))
                    .map(id -> getUserInfos(id))
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            res.addAll(validUsers);
            return res;
        }
    

      上面代码非常简单,就是通过一批用户Id去获取出来完整的用户信息,获取前要对入参做校验,之后还会对id做合法性校验。 上面代码的问题是 res对象初始化太早了,如果一个UserInfo没查到,res对象就白初始化了。另外,最后直接返回validUsers是不是就行了,没必要再装到res中,这里res就具备了非必要性。
      像上述这种情况,可能在很多业务系统里随处可见(但不一定这么直观),提前初始化一些之后没用的对象,除了浪费内存和CPU之外,也会给GC增加负担。

    缩小对象体积

      缩小体积对象也很好理解,如果对象在单位时间内生成的对象数量固定,但体积减小后,同样大小的内存就能装载更多的对象,更晚才触发GC,GC的频次就会降低,频次低了自然对性能的影响就会变小。
      关于减少对象体积,这里我给大家推荐一个jar包——eclipse-collections,其中提供了好多原始类型的集合,比如IntMap、LongMap…… 使用原始类型(int,long,double……)而不是封装类型(Integer,Long,Double……),在一些数值偏多的业务中很有优势,如下图是我对比了HashSet和eclipse-collections中IntSet在不同数据量下的内存占用对比,IntSet的内存占用只有HashSet的四分之一。
    在这里插入图片描述
      另外,咱在写业务代码的时候,写一些DO、BO、DTO的时候没必要的字段就别加进去了。查数据库的时候,不用的字段也就别查出来了。我之前看到过很多业务代码,查数据库的时候把整行都查出来了,比如我要查一个用户的年龄,结果把他的姓名、地址、生日、电话号码…… 全查出来,这些信息放在Java里面需要一个个的对象去存储的,没有用到部分字段首先就是白取了,其实存它还浪费内存空间。

    缩短对象存活时间

      为什么减少对象的存活时间就能提升GC的性能?总的垃圾对象并没有减少啊! 是的 没错,单纯缩短对象的存活时间并不会减少垃圾对象的数量,而是会减少GC的次数。要理解这个就得先知道GC的触发机制,像Java中当堆空间使用率超过某个阈值后就会触发GC,如果能缩短对象的时间,那每次GC就能释放出来更多的空间,下次GC也就会来的更迟一些,总体上GC次数就会减少。
      这里我举个我自己经历的真实案例,我们之前系统有个接口,仅仅是调整了两行代码的顺序,这个接口的性能就提升了40%,这个整个服务的CPU使用率降低了10%+,而这两行顺序的改动,缩短了大部分对象的生命周期,所以导致了性能提升。

        private List<Object> filterTest() {
            List<Object> list = getSomeList();
            List<Object> res = list
                    .stream()
                    .filter(x -> filter1(x))  // filter1需要调用外部接口做过滤判断,性能低且过滤比例很少
                    .filter(x -> filter2(x))  
                    .filter(x -> filter3(x))  // filter3 本地数值校验,不依赖外部,效率高且过滤比例高
                    .collect(Collectors.toList());
        }
    

      上面代码中,filter1性能很低但过滤比低,filter3恰恰相反,往往没被filter1过滤的会被filter3过滤,做了很多无用功。这里只需要将filter1和filter3互换下位置,除了减少无用功之外,List中的大部分对象生命周期也会缩短。
      其实有个比较好的编程习惯,也可以减少对象的存活时间。其实在本系列的第篇中我也大概提到过,那就是缩小变量的作用域。能用局部变量就用局部变量,能放if或者for里面就放里面,因为编程语言作用域实现就是用的栈,作用域越小就越快出栈,其中使用到的对象就越快被判断为死对象。


      除了上述三种优化GC的方式话,其实还有种骚操作,但是我本人不推荐使用,那就是——堆外内存

    堆外内存

      在Java中,只有堆内内存才会受GC收集器管理,所以你要不被GC影响性能,最直接的方式就是使用堆外内存,Java中也提供了堆外内存使用的API。但是,堆外内存也是把双刃剑,你要用就得做好完善的管理措施,否则内存泄露导致OOM就GG了,所以不推荐直接使用。但是,凡事总有但是,有一些优秀开源代码,比如缓存框架ehcache就可以让你安全的享受到堆外内存的好处,具体使用方式可以查阅官网,这里不再赘述。


      好了,今天的分享就到这里了,看完你可能会发现今天的内容和上一讲 (二)巧用数据特性有一些重复的内容,没错,我理解性能优化底层都是同一套方法论,很多新方法只是以不同的视角在不同领域所衍生出来的。最后感谢下大家的支持,希望你看完文章有所收获。另外有兴趣的话也可以关注下本系列的前两篇文章。

    如何写出高性能代码系列文章


    在这里插入图片描述

    展开全文
  • 操作系统使得计算机硬件对程序员透明,即程序员在代码时不用考虑机器到底如何工作。但是了解CPU内高速缓存的作用能帮助程序员设计出更高效的代码。下面简单介绍一下CPU内的高速缓存和程序优化方法 CPU的高速缓存 ...
  • 工作中的sql优化回顾

    2022-03-15 15:26:36
    sql优化记录在这
  • Flutter 学习与性能优化总结

    千次阅读 2022-03-07 11:26:42
      新人年前刚刚加入本地生活,有幸负责的模块使用Flutter编写,在三个月的开发过程中,在原有Demo自学基础上又学到了很多,谨以此篇文章做一个Flutter阶段性的学习和总结,以便于往后的学习过程中温故而知新,那么...
  • 【前端开发】代码结构及性能优化总结

    千次阅读 多人点赞 2021-06-05 13:40:19
    开发环境不做无意义的工作如提取 css 计算文件hash等 配置 devtool 优化构建时的搜索路径 指明需要构建目录及不需要构建目录 7. 加载优化: 合并CSS、JavaScript 合并小图片、使用精灵图 缓存一切可缓存的资源 使用...
  • 前端开发工作总结

    千次阅读 2021-12-18 23:30:48
    从我进入公司到现在已经有一段时间了,随着工作年限的增加,逐渐成长为一名独立的开发人员,角色改变了,职责也改变了。...现将我这段时间的工作总结如下: 项目方面 在过去这段时间里,主要担负项
  • 冰河亲历的亿级流量下的MySQL优化实战,强烈建议收藏!!
  • 【安卓性能优化总结】 【八年工作经验精华积累】 目录 最全的性能优化总结: 零、 启动优化 1、项目背景 2、 检测启动时间 3、打印启动时间 4、优化理念: 5、启动时透明页优化: 6、MultiDex优化 7、多进程时,...
  •   本文是《如何出高性能代码》系列的第四篇,本文将告诉你数据访问会怎么样影响到程序的性能,以及如何通过变更数据访问的方式提升程序的性能。  程序的运行的每一个可以简化为这样一个三步模型:第一步,读...
  • Android性能优化总结

    千次阅读 2021-08-05 00:02:42
    做过一点性能优化工作,现在对工作中的优化点做一个总结。如有错误,还请指正。 有哪些方面需要优化 在平时的优化过程中我们需要从哪几个点来优化呢?其实我们平时自己一定也用过软件,在使用软件的过程中有没有...
  • 不过这一段日子总是有一种冲动想要点什么,把自己了解的有关Blackfin C语言优化和系统优化方面的技巧和知识下来,和正在从事这方面工作朋友们分享,也许有些帮助,也算是对自己过去一段时间工作总结。...
  • 干货:MySql性能优化总结详解

    千次阅读 2021-10-20 14:38:25
    IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是IO操作所占用的,减少IO次数是SQL优化中需要第一优先考虑,当然,也是收效最明显的优化手段。 02 降.
  • 工作时手写的安卓扩展知识总结(自定义view、图片、动画、消息机制、进程间通信、性能优化、四大组件工作过程、图片加载及Glide解析、RxJava解析),字不是很好看,主要自己看,如果有需要也可以拿去参考。...
  • 关于Xcode编译性能优化的研究工作总结本文为原创文章,转载注明出处,谢谢!本文链接:关于Xcode编译性能优化的研究工作总结近来(8月1–8月12)结合Xcode的官方文档和网上资料经验对Xcode的一些配置选项进行了编译...
  • 帆软报表优化总结

    千次阅读 2019-01-29 10:13:28
    date: 2019/1/24 11:17:16 前言 之前在做报表时没有注意那么多细节,上次给甲方公司做他们总公司汇总,明细报表,这种报表动辄几十...因此找到了帆软官方中对于报表性能优化的多个文章,进行仔细查看和对SQL优化处...
  • 如何优化MySQL千万级大表,我了6000字的解读

    万次阅读 多人点赞 2019-10-21 20:03:03
    千万级大表如何优化,这是一个很有技术含量的问题,通常我们的直觉思维都会跳转到拆分或者数据分区,在此我想做一些补充和梳理,想和大家做一些这方面的经验总结,也欢迎大家提出建议。 从一开始脑海里开始也是...
  • 2019新的一年已经到来,如何制定个人it工作计划呢? 下面是收集整理的it个人工作计划,欢迎阅读。 下手方向 其实无论你是否是IT行业都可以从...根据对年度的“整体”性思考,然后罗列出工作总结的“大纲”,最后...
  • 此工具是本人经过长期的学习总结和实践应用而出来的一款小巧的优化设置辅助工具,目前大小不到2M,绿色无污染。借鉴了软媒优化大师和Dism++工具的优化内容以及IT天空热心坛友们和系统封装QQ群友们的经验,并经过...
  • SEO网站优化步骤超详细完整版教程

    千次阅读 2022-03-09 13:50:15
    3 、SEO工作 ①PC站优化:网站架构、页面关系、代码优化、链接推送等;WAP优化:继承PC站的优化成果,进行代码优化、移动适配; ②内容发布:管理原创内容、转载内容、用户内容的更新频率与数量; ③数据分析:关注...
  • MySql基础知识总结(SQL优化篇)

    万次阅读 多人点赞 2021-07-10 12:26:26
    作者简介:CSDN2021博客之星亚军、新星计划导师✌、博客专家 哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师 关注公众号【哪吒编程】,回复1024,获取Java学习路线思维导图、大厂面试真题、加入万粉计划...
  • MySQL SQL和索引优化总结

    千次阅读 2022-03-28 16:38:17
    文章目录一、SQL语句和索引的优化二、应用优化三、MySQL Server优化1. 自适应哈希索引2. redo log3. MySQL查询缓存4. MySQL线程缓存5. 并发连接数量和超时时间 首先我们需要知道MySQL主要是从以下3个方面进行优化: ...
  • SQL优化最干货总结 - MySQL(2020最新版)

    万次阅读 多人点赞 2020-06-29 16:55:47
    MySQL - SQL优化干货总结(吐血版),别辜负了自己的梦想,欢迎白嫖、点赞、收藏。
  • 阐述了作者倡导的“从本质和原理入手,以不变应万变”的优化思路,最后还介绍了作者在实际工作总结出来的Oracle数据库里SQL优化的方法论。 《基于Oracle的SQL优化》适用于使用Oracle数据库的开发人员、OracleDBA和...
  • 阐述了作者倡导的“从本质和原理入手,以不变应万变”的优化思路,最后还介绍了作者在实际工作总结出来的Oracle数据库里SQL优化的方法论。 《基于Oracle的SQL优化》适用于使用Oracle数据库的开发人员、OracleDBA和...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 341,718
精华内容 136,687
热门标签
关键字:

优化工作报告怎么写