目录
九:ArrayList、Vector、LinedList的对比.
1.JVM调优
2.mysql调优
首先,我们必须对explain有一定的了解
(1)如何定位并优化慢查询SQL?
一般有3个思考方向
1.根据慢日志定位慢查询sql
2.使用explain等工具分析sql执行计划
3.修改sql或者尽量让sql走索引
(2)打开查询日志
此处我们要注意的就是设置慢查询阈值
set global long_query_time=1;
只要你的SQL实际执行时间超过了这个阈值,就会被记录到慢查询日志里面。
这个阈值默认是10s,线上业务一般建议把long_query_time设置为1s,如果某个业务的MySQL要求比较高的QPS,可设置慢查询为0.1s。
(3)索化表结构,让查询走索引
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引,避免无索引行锁升级为表锁
2.最左前缀法则
如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。
1 EXPLAIN SELECT * FROM employees WHERE name = 'Bill' and age = 31;
2 EXPLAIN SELECT * FROM employees WHERE age = 30 AND position = 'dev';
3 EXPLAIN SELECT * FROM employees WHERE position = 'manager';
3.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
因为你操作后得到得字符,到索引B+树里面去找,是找不到得!
4.存储引擎不能使用索引中范围条件右边的列
例如这个图,查找name=Bill,age>29 and position=“dev” 中这个dev不会走索引,因为age已经根据大小排好了,那么下一列得position肯定是无序得,只能全表扫描
5.尽量使用覆盖索引(只访问索引的查询(索引列包含查询列)),减少 select * 语句
6.mysql在使用不等于(!=或者<>),not in ,not exists 的时候无法使用索引会导致全表扫描 < 小于、 > 大于、 = 这些,mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引
7.is null,is not null 一般情况下也无法使用索引
8.like以通配符开头('$abc...')mysql索引失效会变成全表扫描操作
一般通配符在前面走不了索引,在后面可以
问题:解决like'%字符串%'索引不被使用的方法?
a)使用覆盖索引,查询字段必须是建立覆盖索引字段
1 EXPLAIN SELECT name,age,position FROM employees WHERE name like '%Lei%';、
b)如果不能使用覆盖索引则可能需要借助搜索引擎
9.字符串不加单引号索引失效
10.少用or或in,用它查询时,mysql不一定使用索引,mysql内部优化器会根据检索比例、表大小等多个因素整体评 估是否使用索引,详见范围查询优化
三:创建线程的方式
- 继承Thread
- 实现runnable
- 实现callable
- 使用Executors关键字
四:线程间通信的几种方式
(1)使用voliatle关键字或者synchronized关键字
使用voliatle可以使多个线程同时监听一个变量,当一个变量发生改变时,他对应的共享内存的值也会相应发生改变
synchronized关键字保证被修饰的方法或者代码块保证只能被一个线程获取
(2)使用wait和notify/notifyAll
wait()/notify()/notifyAll() 必须配合 synchronized 使用,wait 方法释放锁,notify 方法不释放锁。wait 是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify()notify并不释放锁,只是告诉调用过wait()的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放,调用 wait() 的一个或多个线程才会解除 wait 状态,重新参与竞争对象锁,程序如果可以再次得到锁,就可以继续向下运行。
CountDownLatch 基于AQS框架,相当于也是维护了一个线程间共享变量 state。
(4)使用ReentrantLock结合 Condition
(5)基本 LockSupport 实现线程间的阻塞和唤醒
五:索引的作用
- 创建唯一索引,可以保证数据库中每一行数据的唯一性
- 可以加速表和表之间的连接
- 根据索引查询可以快速定位到我们想要查询到的数据,加快数据的检索速度
- 在使用分组和排序 子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
六:创建索引的原则
- 主键自动创建索引
- 经常需要查询的条件创建索引
- 经常用在连接的键上,尤其是外键,创建索引
- 经常需要范围查找的列创建索引
- 经常需要使用where字句的列上创建索引
七:SpringIOC SpringAop加载流程
八:Redis类型
String
List
set
scort set
hash
九:ArrayList、Vector、LinedList的对比.
ArrayList, LinkedList 不是线程安全的,而 Vector 是线程安全的。
ArrayList 和 Vector 都是使用 Object的数组形式来存储的,LinkedList 使用双向链表实现存储
十:servlet的生命周期
Servlet的生命周期
servlet的生命周期顾名思义就是从servlet出现到消亡(销毁)的全过程。
主要分为以下几个阶段:
加载类—>实例化(为对象分配空间)—>初始化(为对象的属性赋值)—>请求响应(服务阶段)—>销毁
servlet生命周期三个方法:
- init()初始化阶段
- service()处理客户端请求阶段
- destroy()终止阶段
- 容器(tomcat等)装载servlet
实例化阶段
1.1 当客户端首次发送第一次请求后,由Servlet容器去解析请求,根据请求找到是否有对应的servlet。
1.2 判断是否有Servlet实现类的对象存在?存在则直接使用,不存在则先创建一个servlet实现类的对象。
初始化阶段
Servlet 初始化是其生命周期的第一个阶段,也是其他阶段的基础。只有完成了初始化,Servlet 才能处理来自客户端的请求。
Servlet 初始化阶段分为 2 步:
加载和实例化 Servlet;
调用 init() 方法进行初始化
1.加载和实例化
Servlet 容器负责加载和实例化 Servlet。
当容器启动或首次请求某个 Servlet 时,容器会读取 web.xml (配置load-on-startup=1,默认为0)或 @WebServlet 中的配置信息,对指定的 Servlet 进行加载。加载成功后,容器会通过反射对 Servlet 进行实例化。
2.调用 init() 方法进行初始化
加载和实例化完成后,Servlet 容器会创建一个servlet对象并调用servlet的init方法(在servlet生命周期内只能调用一次init方法)去初始化 Servlet 实例。
请求响应阶段
初始化完成后调取service()方法,由service()判断客户端的请求方式。
3.1 如果是get请求,则执行doGet()方法。
3.2 如果是post请求,则执行doPost()。
3.3 处理方法完成后会作出相应的结果返回给客户端,单次请求处理完毕。
当用户发送第二次以后的请求时,会判断对象是否存在,但是不再执行init(),而直接执行service方法调取doGet() / doPost()方法。
服务终止阶段
当服务器关闭,重启或移除 Servlet 实例时Servlet调取destroy()方法进行销毁,宣告生命周期的结束。