4399面经

4399面经

sql调优

创建索引

  • 尽量避免全表扫描,考虑在where及order by涉及的列上建立索引

  • 在经常需要进行检索的字段上创建索引

    • 一个表的索引数最好不要超过6个,若太多应考虑不常使用的索引是否有必要。索引不是越多越好,虽然提高查询效率,但降低了insert和update的效率,insert和update可能会重建索引。且InnoDB的索引会占据表空间,减少表数据的存储。

避免在索引上使用计算

在where字句中,如果索引列是计算或者函数的一部分,将不会使用索引而使用全表查询,同时在in和exists中通常使用exists,因为in不走索引

/*效率低*/
select * from user salary*22>11000

/*效率低*/
select * from user salary>11000/22

使用预编译查询

程序中通常是根据用户的输入来动态执行sql,这是应该尽量使用参数化sql,这样不仅可以避免sql注入漏洞攻击,最重要数据库会对这些参数化sql进行预编译,这样第一次执行的时候DBMS会为这个sql进行查询优化并且执行预编译,这样以后再执行这个sql的时候就直接使用预编译的结果,这样可以大大提高执行的速度

调整Where字句中的连接顺序

DBMS一般采用自下而上的顺序解析where字句,根据这个原理表连接最好写在其他where条件之前,那些可以过滤掉最大数量记录----排除越多的条件放在第一个

在用MySQL查询数据库的时候,连接了很多个过滤条件,发现非常慢。例如:SELECT … WHERE p.languages_id=1 AND t.type=1 AND p.products_id IN (472,474),这样查询需要20多秒,虽然在各个字段上都建立了索引。用分析Explain SQL一分析,发现在第一次分析过程中就返回了几万条数据:WHERE p.languages_id=1 ,然后再依次根据条件缩小范围。

然后稍微改变一下WHERE字段的位置之后,速度就有了明显地提高:WHERE p.products_id IN (472,474) AND p.languages_id=1 AND t.type=1,这样第一次的过滤条件是p.products_id IN (472,474),它返回的结果只有不到10条,接下来还要根据其它的条件来过滤,自然在速度上有了较大的提升。经过实践发现,不要以为WHERE中的字段顺序无所谓,可以随便放在哪,应该尽可能地第一次就过滤掉大部分无用的数据,只返回最小范围的数据。

尽量将多条sql语句压缩到一句sql中

每次执行sql的时候都要建立网络连接,进行权限校验,进行sql语句的查询,发送执行结果,这个过程非常耗时,因此应该尽量避免过多的执行sql语句,能够压缩到一句sql执行的语句就不要用多条来执行

用where字句替换having字句

避免使用having字句,因为having只会在检索出所有结果之后才对结果进行过滤,而 where则是在聚合前筛选记录,如果能通过where字句限制记录的数目,那就能减少这方面的开销。HAVING中的条件一般用于聚合函数 的过滤,除此之外,应该将条件写在where字句中。

使用表的别名

当在SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个列名上。这样就可以减少解析的时间并减少哪些有列名歧义引起的语法错误。

用union all替换union

当SQL语句需要union两个查询结果集合时,即使检索结果中不会有重复的记录,如果使用union这两个结果集 同样会尝试进行合并,然后在输出最终结果前进行排序,因此如果可以判断检索结果中不会有重复的记录时候,应该用union all,这样效率就会因此得到提高。

查询select语句优化

  • 尽量不使用*号查询,用具体的字段代替,不要返回用不到的字段
  • 避免在where字句中对字段进行null值判断,否则引擎放弃使用索引而进行全表查询

索引失效

  1. like以%开头,索引无效,当like前缀没有%,后缀有%,索引有效
  2. or语句前后没有同时使用索引。当or左右查询只有一个是索引,该索引失效。
  3. 组合索引,不是使用第一索引,索引失效
  4. 数据类型出现隐式转化。如varchar不加单引号的话可能自动转换为int型,使索引无效,产生全表扫描
select * from emp where job="123";
select * from emp where job=123; --索引失效

5.在索引列上使用IS NULL或IS NOT NULL操作。索引是不索引空值的

select * from emp where ename is not null;

6.在索引字段上使用not,<>,!=是用不到索引的,对他的处理只会产生全表扫描

7.对索引字段进行计算操作、使用函数

8.全表扫描速度比索引速度快时,mysql会使用全表扫描,索引失效

session与cookie的关系

session是依赖cookie实现的,服务器默认为浏览器在cookie中设置sessionid,浏览器在向服务器请求过程中传输cookie包含sessionid,服务器根据sessionid获取出会话存储的信息

  1. 数据存储

    cookie以明文的方式存储在浏览器端,session存储在服务器端

  2. 安全性

    由于存储位置的原因,也就出现了浏览器端是不安全的,服务端更为安全

  3. 生命周期

    cookie的生命周期是可以累计时间,即到点就失效;Session是以最后 一次访问时间为倒计时的开始时间,同时,它还可以直接调用api来使它失效

  4. 使用原则

    cookie的缺陷,每个站点只能保存20个cookie,每个cookie大小4k以内,session是存放服务器端,会占用服务器内存,因此不要往session中存放过多过大的对象

Java锁

  • 乐观锁/悲观锁

    • 乐观锁:每次拿数据时都认为别人不会修改,所以不会上锁,但在更新的时候会判断在此期间别人有没有去更新这个数据,可以使用版本号等机制。适合多读的应用类型,这样可以提高吞吐量。
    • 悲观锁: 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,每次拿数据的时候都会上锁,别人想拿到这个数据就会阻塞直到它拿到锁

    悲观锁适合写操作非常多的场景,乐观锁适合读操作非常多。

    悲观锁在Java中的使用,就是利用各种锁

    乐观锁在Java中的使用,是无锁编程,常常使用的是CAS算法

  • 独享锁/共享锁

    独享锁是指该锁一次只能被一个线程所持有

    共享锁是指该锁可以被多个线程持有

    对于ReentrantLock而言,是独享锁。但是对于ReadWriteLock,其读锁是共享锁,其写锁是独享锁

  • 互斥锁/读写锁

    独享锁和共享锁是广义的说法,互斥锁/读写锁就是具体的实现

    互斥锁在Java中的具体实现就是ReentrantLock

    读写锁在Java中的具体实现就是ReadWriteLock

  • 可重入锁

    可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。

  • 公平锁和非公平锁

    公平锁指多个线程按照申请锁的顺序来获得锁

    非公平锁指多个线程获取锁的顺序不是按申请锁的顺序,由CPU调度

  • 分段锁

    分段锁其实是一种锁的设计,并不是具体的一种锁,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。

    我们以ConcurrentHashMap来说一下分段锁的含义以及设计思想,ConcurrentHashMap中的分段锁称为Segment,它即类似于HashMap(JDK7和JDK8中HashMap的实现)的结构,即内部拥有一个Entry数组,数组中的每个元素又是一个链表;同时又是一个ReentrantLock(Segment继承了ReentrantLock)。

    当需要put元素的时候,并不是对整个hashmap进行加锁,而是先通过hashcode来知道他要放在哪一个分段中,然后对这个分段进行加锁,所以当多线程put的时候,只要不是放在一个分段中,就实现了真正的并行的插入。

    但是,在统计size的时候,可就是获取hashmap全局信息的时候,就需要获取所有的分段锁才能统计。

    分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。

  • 偏向锁/轻量级锁/重量级锁

    偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。

    轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。

    重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让他申请的线程进入阻塞,性能降低。

  • 自旋锁

    在Java中,自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。

OSI七层模型

–开放式系统互联

  1. 物理层
  2. 数据链路层
  3. 网络层
    1. IP协议
  4. 传输层
    1. TCP协议
  5. 会话层
  6. 表示层
  7. 应用层
    1. HTTP协议

TCP/IP五层模型

  1. 物理层
  2. 数据链路层
  3. 网络层
  4. 传输层
  5. 应用层
    • 会话层
    • 表示层
    • 应用层

http协议的端口

常用端口号:80/8080/8081/3128/9098

创建线程池的方法

线程池七大参数:最大线程池大小,最大核心线程大小,超时等待时间,超时时间单位,阻塞队列,线程工程,拒绝策略

如何保证线程安全

  • 互斥同步

    • ReentrantLock
    • synchronized
  • 非阻塞同步

    • CAS:未获得资源,循环等待不阻塞
  • 无须同步方案

    • 线程不涉及共享资源

MyISAM与InnoDB的区别

  • 存储结构

    • MyISAM每个表都分为三个文件:表格定义,数据文件,索引文件
    • InnoDB所有表都保存在一个数据文件中,InnoDB表大小只受限于操作系统文件的大小,一般为2GB
  • 存储空间

    • MyISAM可被压缩,存储空间较小
    • InnoDB的表需要更多的内存和存储,它会在主内存中建立专用的缓冲池用于高速缓存数据和索引
  • 记录存储顺序

    • MyISAM按插入顺序保存
    • InnoDB按主键大小有序插入
  • 外键

    • MyISAM不支持
    • InnoDB支持
  • 事务

    • MyISAM不支持
    • InnoDB支持
  • 锁支持

    • MyISAM只有表锁
    • InnoDB有行锁和表锁,默认行锁,行锁在查询字段带有索引的时候才会触发,不然还是使用表锁
  • select count(*)

    MyISAM更快,内部维护了一个计数器可以直接调用

  • 索引

    • 都是B+树索引
  • 哈希索引

    • MyISAM不支持
    • InnoDB支持
  • 全文索引

    • MyISAM支持
    • InnoDB不支持
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值