1.普通索引
2.主键索引
3.唯一索引
4.组合索引
1.MyISAM 是非事务的存储引擎,适合用于频繁查询的应用。表锁,不会出现死锁,适合小数据,小并发。
2.innodb是支持事务的存储引擎,合于插入和更新操作比较多的应用,设计合理的话是行锁(最大区别就在锁的级别上),适合大数据,大并发。
1.主键不允许为空值,唯一索引允许有空值
2.一个主键,多个唯一索引
3.主键可以被其他表引用为外键,唯一索引列不可以
4.主键是约束,唯一索引是索引
5.主键一定会创建一个唯一索引,但是有唯一索引的列不一定是主键
会, 死锁就是互相占用对方的资源。
1.设置mysql等锁的最大时间,时间一到就回滚。
2.优化sql语句
1.(聚集索引)列值的顺序与数据的物理顺序相同 主键就是聚集索引 一个表中只有一个聚集索引
2.(非聚集索引)列值的顺序与数据的物理顺序不同 一个表中可以拥有多个非聚集索引
存放的是数据本身
存放的是数据的地址
久储存、有组织、可共享
查看 执行计划 EXPLAIN
explain(执行计划)包含的信息十分的丰富,着重关注以下几个字段信息。
1.id,select子句或表执行顺序,id相同,从上到下执行,id不同,id值越大,执行优先级越高。
2.type,type主要取值及其表示sql的好坏程度(由好到差排序):system>const>eq_ref>ref>range>index>ALL。保证range,最好到ref。
3.key,实际被使用的索引列。
4.ref,关联的字段,常量等值查询,显示为const,如果为连接查询,显示关联的字段。
5.Extra,额外信息,使用优先级Using index>Using filesort(九死一生)>Using temporary(十死无生)。
使用优先级Using index>Using filesort(九死一生)>Using temporary(十死无生)。也就说出现后面两项表明sql语句是非常烂的,急需优化!!!
①最佳左前缀法则。
1.在等值查询时,更改索引列顺序,并不会影响explain的执行结果,因为mysql底层会进行优化。
2.在使用order by时,注意索引顺序、常量,以及可能会导致Using filesort的情况。
②group by容易产生Using temporary。
③通俗理解口诀:
全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
LIKE百分写最右,覆盖索引不写星;
不等空值还有or,索引失效要少用。
char ,固定长度, 指定长度后,如果值不够则后面空格自动补齐
vachar 非固定长度,指定最长的长度
所有存储引擎对每个表至少支持16个索引
1.查询慢查询日志
2.执行 EXPLAIN分析索引是否失效
3.优化sql的108条军规
4.show profile 查询最近15条记录和耗时(Show Profile是mysql提供的可以用来分析当前会话中sql语句执行的资源消耗情况的工具,可用于sql调优的测量。默认情况下处于关闭状态,并保存最近15次的运行结果。)
show profile all,block all for query X;
1.读锁
2.写锁
3.行级锁,会产生死锁,可以设置等待锁的最长时间,时间一到自动回滚
4.间隙锁 (间隙锁是锁范围不是锁数据,mysql利用间隙锁+行锁在实现虽然事务是可重复读级别,但是却实现了串行化级别的效果)
利用for update
ps: select * from student s where s.name = 'zhangsan' for update;
①尽可能让所有数据都通过索引来完成,避免无索引行锁升级为表锁。
②合理设计索引,尽量缩小锁的范围。
③尽可能使用较少的检索条件,避免间隙锁。
④尽量控制事务大小,减少锁定资源量和时间长度。
⑤尽可能降低事务隔离级别。
①master将改变记录到二进制日志(binary log),这些记录过程叫做二进制日志事件(binary log events)。
②slave将master的binary log events拷贝到中继日志(relay log)。
③slave重做中继日志中的事件,将改变应用到自己的数据库中。MySQL的复制是异步且串行化的。
主从数据库的对应关系为:1对多
in后面跟的是小表,exists后面跟的是大表。
简记:in小,exists大。
ps: select *from tb_emp_bigdata A where A.deptno in (select B.deptno from tb_dept_bigdata B) (A大,B小)
ps: select *from tb_dept_bigdata A where exists(select 1 from tb_emp_bigdata B where B.deptno=A.deptno); (A小,B大)
首先分库分表是两码事
分库是为了提高并发吞吐量
分表:垂直拆分,水平拆分两种
sharding-jdbc:sharding-jdbc 这种 client 层方案的优点在于不用部署,运维成本低,不需要代理层的二次转发请求,性能很高
mycat:mycat 这种 proxy 层方案的缺点在于需要部署,自己运维一套中间件,运维成本高,但是好处在于对于各个项目是透明的,如果遇到升级之类的都是自己中间件那里搞就行了
1.按照 range 来分,就是每个库一段连续的数据,这个一般是按比如时间范围来的,但是这种一般较少用,因为很容易产生热点问题,大量的流量都打在最新的数据上了
2.按照某个字段hash一下均匀分散,好处在于说,可以平均分配每个库的数据量和请求压力;坏处在于说扩容起来比较麻烦,会有一个数据迁移的过程,之前的数据需要重新计算 hash 值重新分配到不同的库或表
1.停机迁移
2.双写迁移方案(1.数据分为历史数据和增量数据,2.历史数据直接迁移即可,3.增量数据的执行语句在原库上执行后要保存入消息队列,4.历史数据迁移完毕后开始读取消息队列的数据给新库执行,5.验证双方的数据是否一致,可以先比对总数据条数然后在新旧库各取50条数据拼接算hash,循环验证)
首先分配主键的时候按照%32来取余存放数据,后期如果增加数据库只需要迁移数据和修改匹配规则即可,不用动代码
1.数据库自增 id (可以各个库先去redis取id号来使用,redis保证主键唯一并且自增)
2.设置数据库 sequence 或者表自增字段步长
3.UUID
4.雪花算法
1. 全局视野法:
如果要获取第N页的数据(每页S条数据),则将每一个子库的前N页(offset 0,limit N*S)的所有数据都先查出来(有筛选条件或排序规则的话都包含),然后将各个子库的结果合并起来之后,再做咱们平时常规的分页查询(可不用带上相同的筛选条件,但还要带上排序规则)即可得出最终结果,这种方式类似es分页的逻辑。
优点:数据准确,可以跳页
缺点:深度分页时的性能差,即随着分页参数增加,网络传输数据量越来越大,每个子表每次需要查询的数据越多,性能也越慢
2. 禁止分页法:
如果要获取第N页的数据,第一页时,是和全局视野法一致,但第二页开始后,需要在每一个子库查询时,加上可以排除上一页的过滤条件(如按时间排序时,获取上一页的最大时间后,需要加上time > ${maxTime_lastPage}的条件;如果没有排序规则,由于是默认主键id的排序规则,也可加上 id > ${maxId_lastPage}的条件),然后再limit S,即可获取各个子库的结果,之后再合并后top S即可得到最终结果。在类似app中列表下拉的场景中,业务上可以禁止跳页查询,此时可以使用这种方式。
优点:数据准确,性能良好
缺点:不能跳页
4. 模糊查询法等:
模糊查询法由于查询的结果不准确,所以小编没有汇总,有兴趣的朋友可以自己研究。