MySQL笔记总结

一、sql基础

1.sql执行顺序

MySQL笔记总结_第1张图片

2.七种join

内连接(两者交集)

select * from tableA a inner join tableB b on a.key=b.key;

左外连接(左表a独有部分加上两者交集,独有部分对应另一个表字段为null)

select * from tableA a left join tableB b on a.key=b.key;

左连接(左表a独有部分)

select * from tableA a left join tableB b on a.key=b.key where b.key is null;

右外连接(右表b的独有加上两者交集)

select * from tableA a right join tableB b on a.key=b.key;

右连接(右表b独有部分)

select * from tableA a right join tableB b on a.key=b.key where a.key is null;

全连接(a表独有加b表独有加两者交集)

select * from tableA a left join tableB b on a.key=b.key

union

select * from tableA a right join tableB b on a.key=b.key;

各自独有部分

select * from tableA a left join tableB b on a.key=b.key where b.key is null

union

select * from tableA a right join tableB b on a.key=b.key where a.key is null;

二、索引

1.说明

索引是帮助数据库高效获得数据的数据结构(排好序的快速查找数据结构,有B树结构、哈希),索引一般本身也很大,往往以索引文件的形式存在磁盘。
索引优势:提高检索效率、降低数据排序成本
索引劣势:实际是索引也是一张表,保存了主键和索引字段,并指向实体表记录,也要占空间;降低更新表的速度

2.索引种类

单值索引:索引只包含单列
唯一索引:列值必须唯一,但允许有空值
复合索引:索引包含多列

3.创建索引

可以使用create index 和alter table add index

4.索引结构

BTree、hash、full-text全文、R-Tree

5.创建索引情形

适合建索引:

主键自动建立唯一索引
频繁作为查询条件的字段
与其它表关联的查询字段
高并发下倾向创建组合索引
索引字段与排序字段、统计分组字段一致,可以提供排序速度

不适合建索引:

数据太少
频繁更新的字段
字段值重复太多(比如性别字段只有男女)
where条件里用不到的字段

三、explain执行计划

1.id:select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序。id相同的执行顺序由上往下;id不同,如果是子查询,id号会自增,值越大优先执行

2.select_type:查询类型,有6种
simple:简单的select查询,不包含子查询和union
primary:查询中包含复杂的字子部分,最外层则被标记为primary
subquery:select或者where中包含子查询
derived:在from列表中包含的子查询被标记为derived(衍生)
union:若 第二个select出现在union之后,则被标记为union;若union包含在from子句的子查询中,最外层select被标记为derived
union result:从union表获得结果的select

3.table:执行的表名

4.type:查询类型,从好到差的排序是system>const>eq_ref>ref>range>index>all,一般来说得保证查询到达range级别,最好ref。
system:表只有一行记录(等于系统表),这是const的特例
const:通过索引一次就找到了,用于比较primary key或者unique索引。如将主键置于where列表中,MySQL就能将该查询转换为一个常量
eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或者唯一索引扫描
ref:非唯一性索引扫描,返回匹配某个单独值所有行,本质上也是一种索引访问
range:只检索给定范围的行,使用一个索引来选择行。一般是在where中出现了between、<、>、in等的查询
index:全索引扫描,index和all都是读全表,但是index只遍历索引数,是从索引中读取,而all是从硬盘读取。index通常比all快,因为索引文件通常比数据文件小。
all:全表扫描

5.possible_keys:可能应用到的索引,若查询字段存在索引,则会被列出来,但不一定会真的使用到。

6.key:实际使用的索引,若为null,则没有使用索引。查询中若使用了覆盖索引(覆盖索引是select查询的字段和顺序,跟创建的复合索引字段和顺序一样),则该索引仅出现在key列表中

7.key_len:显示为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。在不失精度的条件下,长度越短越好。

8.ref:显示索引的哪一列被使用了,如果可能的话,是一个常量。哪些列或常量被用于查找索引列上的值

9.rows:根据表统计信息及索引选用情况,大致估算出找到所需的记录所需读取的行数。

10.Extra:包含不适合在其他列显示,但十分重要的额外信息
Usring filesort:mysql对数据使用了一个外部的索引排序,不是按照表内的索引顺序进行读取。mysql中无法利用索引完成的排序操作称为“文件排序”。
Using temporary:在对查询结果排序时使用了临时表,常见于排序order by和分组查询group by
Using index:表示相应的select操作中使用了覆盖索引,效率不错!如果同时出现using where,表明索引被用来执行索引键值的查找;如果没有同时出现using where,表明索引用来读取数据而非执行查找动作。
Using where:使用了where过滤
Using join buffer:使用连接缓存
impossible where:where子句的值总是false,不能返回任务数据

四、索引优化

1、两表left join查询,在右边关联字段上建索引,这是因为左连接左表一定有,关键点是如何从右表搜索。右连接相反再在左表建索引。

2、如何避免索引失效:

 

(1)遵守最佳左前缀法则:如果索引了多列(复合索引),查询条件的列从索引的最左前开始并且不跳过索引的列。
(2)不在索引列上做任何的操作(计算、函数、类型转换(自动or手动))
(3)索引字段使用范围查询其后面字段索引无效。
(4)索引列使用不等于(!=或者<>)会导致索引失效
(5)is null,is not null无法使用索引
(6)like以通配符开头(%abc)索引失效,以常量开头可以使用索引(abc%)。如果必须like %abc% ,可以使用覆盖索引(即查询的列就是索引列)
(7)索引列配置时条件类型不一致索引失效

 

(8)少用or,连接时会索引失效

 

五、查询优化

1、查询优化

 (1)优化原则:小表驱动大表
     当A表数据大于B时,用in优于exists(用in是先执行B表子查询,再匹配A表主查询)
     select * from A where id in (select id from B)
     当A表数据小于B时,用exists优于in(exists先执行A表主查询,验证主查询的结果是否在A表)
     select * from A where id exists(select 1 from B whre B.id=A.id)
(2) order by关键字优化

  •  支持两种方式排序index和filesort,尽量使用index,避免使用filesort。index效率高,index是指索引本身完成排序
  • order by会使用index排序的条件:排序使用索引最左前缀原则(如果复合索引多列排序,其排序升降要统一);where条件使用索引的最左前缀是常量,order by也能使用
  • order by使用filesort优化:策略增大sort_buffer_size的参数设置;增大max_length_for_sort_data参数的设置
    filesort两种排序算法:双路排序(4.1版本之前)和单路排序
    双路排序是从磁盘读取排序的字段,在buffer进行排序,再从磁盘读其他字段(两次磁盘io)
    单路排序是从磁盘查询所有列,在buffer进行排序,然后扫描排序后的列表输出。单路排序引出的问题:在sort_buffer中   把所有字段都取出,有可能取出的数据总大小超出了sort_buffer容量,导致每次只能取其容量大小的数据进行排序(创建tmp文件,多路合并),排完后再取容量大小的数据再排

2、慢查询日志
(1)查看是否开启:
    show variables like '%slow_query_log%'(默认是关闭)
(2)开启慢查询:
    set global slow_query_log=1(只对当前数据库生效,mysql重启后失效)
   永久生效修改配置my.cnf,global slow_query_log=1和slow_query_log_file=日志路径(如果没有指定默认文件是       host_name-show.log)
(3)查看慢查询sql阈值时间(大于阈值sql才会记录):
    show variables like '%slow_query_time%'(默认是10秒)
(4)设置阈值时间:
    set global slow_query_time=5
    (修改后看不到变化:需要重新连接会话或者使用命令show variables like '%slow_query_time%')
(5)查看有多少条慢sql:
    show global status like '%slow_queries%'

 

(6)日志分析工具mysqldumpslow

 

3、show profile
(1)是MySQL提供可以用来分析当前会话中语句执行的资源消耗情况。可以用于sql的调优的测量。默认是关闭状态,并保存最近15次的运行结果
(2)查询是否开启
    show variables like 'profiling'
(3)设置开启
    set profiling=on
(4)查看sql运行结果
    show profiles
(5)诊断sql
    show profile cpu,block io for query 上面运行结果的query_id
    出现问题的信号:
    converting heap to myisam 查询结果太大,内存不够用
    creating temp  table 创建临时表(拷贝数据到临时表,用完再删除)
    coping to tmp table on disk把内存中临时表复制到磁盘
    locked

 

六、数据库锁

 

1、MyISAM

(1)读锁(共享)

  一个会话锁了A表,当前会话只能查询A表,不能修改A表,也不能操作其他表;其他会话可以查询A表和数据库其他表,修改A表会堵塞等待

 

(2)写锁(独有)

一个会话锁了A表,当前会话只能查询、修改A表,不能操作其他表;其他会话不能操作A表会堵塞等待,可以操作数据库其他表

(3)命令

查看哪些表锁了:show open tables

分析表锁定:show status  like 'table%'

Table_locks_immediate:产生表锁的次数

Table_locks_waited:锁争用而等待的次数

总结:读锁会堵塞写,不会堵塞读;写锁会堵塞读写。myisam的读写调度是写优先,它不适合做以写为主的引擎。

 

2、InnoDB

(1)与myisam区别

innodb支持事务和采用行锁

(2)索引失效,导致行锁变表锁

比如一个vachar2字段建立索引,修改where 匹配时输入是number,类型不匹配

(3)间隙锁

当使用范围条件的时候,会锁定整个范围内所有的索引键值,即使这个键值不存在。会导致无法插入锁定内范围的任何数据。

(4)锁查看分析

MySQL笔记总结_第2张图片

七、事务

1、事物隔离级别

读未提交:read uncommitted :事物A和事物B,事物A未提交的数据,事物B可以读取到
读已提交:read committed:事物A和事物B,事物A提交的数据,事物B才能读取到
可重复读:repeatable read:事务A和事务B,事务A提交之后的数据,事务B读取不到,事务B是可重复读取数据
串行化:serializable:事务A和事务B,事务A在操作数据库时,事务B只能排队等待

脏读 : 一个事务读取到另一事务未提交的更新数据
不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说, 
后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次
读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
幻读 : 一个事务读到另一个事务已提交的insert数据
 MySQL笔记总结_第3张图片
 注:InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了可重复读下幻读问题

大多数数据库的默认隔离级别为: Read Commited,如Sql Server , Oracle.

少数数据库默认的隔离级别为Repeatable Read, 如MySQL InnoDB存储引擎

2、事物传播行为

PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。

PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘

PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。

PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

 

 


    

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(笔记总结--数据库,工具类)