学习笔记:MySql

MYSQL

基础知识:

sql注入:

当sql语句绑定有参数输入时,可通过外部更改URL的方式,将sql语句进行更改(union),这样就可以在未获取正确数据的情况下访问系统,对系统的安全性造成破坏

mybatis如何在插入数据后获取主键值:xml中useGeneratekeys属性设置为true

数据库中间件技术:

mycat,当mysql设为集群架构时,项目连接mycat,mycat连接mysql集群,这样项目就感觉直接连了一个mysql,而不是mysql集群。

sql执行的步骤:

from join on where groupby having select disInct orderby limit

mysql的索引优化:

索引就是一个用来排序+查找的数据结构,它底层是用B+树实现,一个表中最多可建立16个索引

  • 创建索引的方式:createIndex xxx on tableName(字段1,字段2)
  • 删除索引的方式:dropIndex xxx on tableName
  • 查看索引的方式:show Index from tableName

mysql中的存储引擎:InnoDB MyIsam

InnoDB和MyIsam的区别:

  • 一:InnoDB支持行锁(innodb只有在使用索引时采用行锁,其他情况使用表锁),MyIsam是表锁
  • 二:InnoDB支持事务,MyIsam不支持事务
  • 三:InnoDB支持外键,MyIsam不支持外键
  • 四:InnoDB支持聚集索引,MyIsam不支持
  • 五:InnoDB的数据文件:.frm:表结构,.ibd:索引+数据,MyIsam的数据文件:.frm:表结构,.MYI:索引,.MYD:数据

索引:

索引的种类

  • 唯一索引:所建立的索引所属列的值必须是唯一的,且可以为null
  • 复合索引:一个索引中包含多个列
  • 单值索引:一个索引只包括单个列,一个表中可以有多个单值索引
  • 聚集索引:也就是主键索引,每个表中只要有主键那么该主键就自带聚集索引,若没有主键那么mysql会选择一个值不重复的列作为聚集索引,若不存在则它会建立一个隐藏的自增字段作为聚集索引

聚集索引和非聚集索引的区别?

聚集索引要求字段的值唯一,聚集索引在叶子节点存放的是表中所有的数据,非聚集索引在叶子节点存放的是主键id和索引列对应的数据
(非聚集索引不采用覆盖索引时要进行回表操作)

覆盖索引:

指要查询的字段都属于一个索引中的字段,就称为覆盖索引,无需做回表操作,(回表:当要查询的字段大于索引的字段时,需要回表到聚簇索引中再查询二级索引中不包括的字段对应的值)

哪些列适合作为索引?

  • 经常被查询的列
  • 数据量大
  • 值大多都不重复的
  • 外连接查询时On条件后面的字段,经常用于排序的列

哪些情况不适合建立索引?

  • 列中有很多重复的值
  • 经常用于增删改的列
  • 表记录太少

索引失效的原因:

  • 一:未遵循最佳左前缀原则,where条件查询时,应该按照索引的顺序进行查询,不能缺少索引中的字段(缺少的字段后面的索引字段将失效),全职匹配我最爱
  • 二:范围查找后失效(> < !=),范围查找会导致索引失效,范围超找后面的条件会用不到索引
  • 三:不在索引列上做操作,如在where条件后的字段做(函数,类型转换)会导致索引失效
  • 四:like查询时%最好用在右边,否则会导致索引失效(除非采用覆盖索引(要查询的列和索引的列正好匹配))
  • 五:is null 和is not null和or 会导致索引失效
  • 六:尽量不要使用select *多使用覆盖索引,否则会造成回表操作(当用到我们自己创建的索引后,由于索引中存放的只有对应列的数据,select * 查询的是所有数据,因为还需要到主键索引中去获取对应的所有数据)
  • 七:在使用左连接时,要为右边的表建立索引,在使用右连接时,要为左边的表建立索引

sql优化:

  • ①:当大批量插入数据时,可以采用foreach标签批量插入而不是在JAVA中使用for循环插入
  • ②:优化limit分页,当查询的数据很靠后eg:limit:10000,10,可以采用:where id>10000 limit 10
  • ③:删除冗余索引,eg:索引1(age) 索引2(age,name) 就可以删除掉索引1,因为索引2包括索引:(age)和(age,name)
  • ④:where子句中考虑使用默认值代替null:where age is not null可以替换成where age >0

索引优化:

Explain+sql语句对sql进行分析
所显示的字段有

  • id(决定查询出来的多个表要执行的顺序):id相同时:执行顺序从上至下,id不同时:id越大的越先执行
  • select_type(显示查询的类型):simple:简单的sql查询 primary:最外层的查询 subquery:子查询
    table(显示该行数据属于哪张表)
  • type(显示该行数据所用的类型):从好到坏 systetm>const>eq_Ref>ref>range>index>all 至少要达到range级别
  • possible_keys:显示可能用到的索引 key:实际用到的索引
  • key_len:索引用到的字节数
  • ref:哪些列用到了索引
  • rows:根据表的信息及索引的信息,估计出需要查找多少行可以找到对应的数据

慢查询日志

在开启慢查询日志后可以借助mysqlDrumpslow工具对慢查询日志进行分析。
SQL执行时间超过long_query_time将会被记录到慢查询日志当中,可以通过explain关键字对其进行分析

show profile(Explain的升级版)记录最近执行的15条sql

mysql的事务:ACID

  • 原子性:事务内的操作要么都成功,要么都失败(mysql用undo log实现)
  • 一致性:事务提交前和提交后,数据库的完整性约束没有被破坏
  • 隔离性:多个事务间是相互隔离的互不影响
  • 永久性:事务提交后,所修改的数据是永久生效的

MVVC:多版本并发控制,在多线程操作数据库时保证事务隔离的机制,可以降低锁竞争的压力,保证较高的并发量

事务的隔离级别(通过mysql锁的机制实现)

  • 读未提交:读取到了还没有提交事务的数据
  • 读已提交:读取到了已经提交的新增数据
  • 可重复度:可以读到已提交的修改数据
  • 可序列化

事务并发带来的问题:

  • 更新丢失:A和B同时更新,后面更新的数据会覆盖掉之前更新的数据
  • 脏读:A读到了B未提交的数据
  • 不可重复度:A读到了B已提交的修改数据
  • 幻读:A读到了B已提交的新增数据

事务的传播机制:

  • Required:B方法在A方法中被调用,若A开启事务,则B就和A用同一事务
  • RequiresNew:B方法在A方法中被调用,若A开启事务,则B开启一个新事务,B和A的事务相互独立
  • Nested:B方法在A方法中被调用,若A开启事务,则B开启一个新事务,当A事务回滚则B事务也回滚,若B事务回滚A没事

主从复制:

将mysql进行主从复制,主库(master)负责写,从库(slave)负责读,实现读写分离和故障切换的高可用
原理:
主库将改变记录到二进制日志中(binary log)
从库读取主库的binary log 日志并拷贝到它的中继日志当中
从库重做中继日志中的事件,将改变应用到自己的数据库中
问题:延时,从库无法第一时间读取到主库新增的数据 解决方法:读取新增数据时,让他强制到主库中进行读取

三大范式

  • 第一范式:数据库中的各个字段,都是不可分割的。(地区:中国山西,这个就可以分割为中国和山西)
  • 第二范式:在满足第一范式的基础上,保证各个字段都是依赖于主键的。(若该字段离开主键照样可以知道值,也不算第二范式)
  • 第三范式:在满足第二范式的基础上,各个字段不能有依赖关系(单价:10 数量:5 总价:50,这个总价就可以通过单价*数量算出来,就不符合第三范式了)

分表技术

分为水平分表和垂直分表(用数据库中间件技术mycat实现)
水平分表:当表中数据太多时,可按行分表(原来200行的表分为2个100行数据的表)
垂直分表:当表中字段太多时,可将一些不常用的字段分离到新的表上,通过外键关联(5个字段的表,分为一个4个字段一个1个字段的表)

mysql5.6后推出的索引下推

可以减少回表次数,它会先在索引表(二级索引)中对索引表中的字段进行判断,直接过滤掉不满足条件的记录,减少回表次数。
eg:查询3个字段,2个在二级索引,1个在聚簇索引中,5.6之前它会根据最左匹配原则只判断第一个条件,得到2个记录然后做两次回表
5.6之后它会判断2个条件,可能只得到1个记录然后做一次回表

常见问题

*唯一索引普通索引选择难题

唯一索引无法使用changebuffer,普通索引可以使用
执行更新操作,判断数据页是否在内存,在内存直接更新,不在内存则将其缓存到changebuffer执行merge操作

一个很长的字段,想做索引我们怎么去优化它

因为字段很长,所以要建立B+树索引的话,索引所占的磁盘空间就越大,搜索效率就不高
可以使用hash索引,把字段hash为另一个字段存起来,每次校验hash就可以了

select *和 select 全部字段的区别

select *要解析数据字典,select 全部字段不需要
select 全部字段更具有可读性
select全部字段 可以按指定字段顺序输出,select *按照建表顺序输出

having和where的区别

having是在分组group by时使用
having在where后执行
having无法用到索引,where可以
having可以用到聚集函数,where不可以

PreparedStatment和Statment区别

statment会频繁编译sql
PreparedStatment可以对sql预编译,提高效率
当sql中有条件时,PreparedStatment可以使用占位符,statment则需要进行拼接,因此statment有SQL注入问题

数据库连接池:

因为每次获取和释放连接都很耗时,因此有了数据库连接池,在项目启动时就建立一定数量的池连接,获取连接时从池中获取,释放连接时,
不是将连接直接释放掉,而是将连接再归还到连接池当中。(底层通过list集合来对连接进行存放)
当有连接请求到连接池,如果有连接处于空闲状态则直接返回一个空闲连接并标记为忙。
如果当前没有空闲连接,就会新建一定数量的连接,新建连接的数量由配置参数决定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guojunjiang12345

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值