MySQL学习记录

1. 左连接、右连接、等值连接
	left join on , right join on
	* on子句连接条件,把表中等值的记录连接在一起,但是不影响记录集合的数量
	  若是left_table中某记录无法在right_table找到,则以NULL代替
 	* where子句控制记录是否符合查询要求,过滤
 	on是局部条件,where全局条件

 	inner join on与where一致过滤(涉及优化)

 2. SQL优化
 	a)显性连接优化
 		等值连接:显性连接(inner join on)和隐性连接(where)
 		* 隐性连接,在from过程中对所有表进行笛卡尔积,最终通过where过滤
 			select * from student s, SC sc, Course c
 			where s.id = sc.id and sc.cId = c.id
 		* 显性连接,在每次表连接时通过on过滤,筛选后的结果集合再和下一个表笛卡尔积,以此循环
 			select * 
 			from (student inner join SC on s.id = sc.id)
 			inner join Course on c.id = sc.cId

 	b)驱动表
 		驱动表是由结果集的数据量来决定的。
 			* 指定了连接条件时,满足查询条件的记录行数少的表为驱动表
 			* 未指定连接条件时,行数少的表为驱动表
 		要想效率高,就是要以小结果集驱动大结果集
 		MySQL下:
 		(1)关键字EXPLAIN:为SQL出现的每张表返回一行信息来说明数据库优化器如何操作这张表
 			EXPLAIN  
 			SELECT * 
 			FROM  ...

 		(2)关键字STRAIGHT_JOIN:按照我们要求的from表顺序执行
 			EXPLAIN  
 			SELECT <STRAIGHT_JOIN> * 
 			FROM  ...

 			注意:应避免查询缓存,所以执行前手动清除(RESET QUERY CACHE)。

 3. 事务特性(ACID)
 		原子性(atomic):要么都执行,要么都不执行。
 		一致性(consistency):从一个一致性状态到另一个一致性状态
 		隔离性(isolation):多个并发事务之要相互隔离
 		持久性(durability):对数据的改变是永久的

4. 数据库隔离级别
	多个事务读可能导致以下问题:
		脏读:事务A读取事务B还没有提交的数据
		不可重复读:一行被检索两次,并且该行中的值在不同的读取之间不同
		幻读:当在事务处理过程中执行俩个相同的查询,并且第二个查询返回的行集合与第一个查询不同(两次读中间差有数据操作,不可重复读是修改了数据,幻读是插入了数据)

				丢失更新		脏读 	不可重复读 	幻读
				
	读未提交:	可能发生	   可能发生	 可能发生   可能发生
	读已提交:	  可能 		不可能		可能 	 可能
	可重复读:	 不可能      不可能      不可能    可能
	可串行化:    不可能	    不可能      不可能    不可能

5. MySQL两种存储引擎的区别(事务、锁级别等等),各自的适用场景
	MYISMA:不支持外键,表锁
		插入数据时,锁定整个表,查表总行数时,不需要全表扫描
	INNODB:支持外键,行锁
		查表总行数时,全表扫描


6. 索引有B+树索引和hash索引
	hash:等值查询效率高,不能排序,不能进行范围查询
	B+树:数据有序,范围查询

7. 聚集索引和非聚集索引
	聚集索引:数据按索引顺序存储,子节点存储真实的物理数据
	非聚集索引:存储指向真正数据行的指针;

8. 索引优缺点,什么时候用或不用
	优点:提高查询效率
	缺点:更新数据时效率低,因为要同时更新索引
	对数据进行频繁的查询时建议使用索引,频繁的更新数据不建议使用索引

9. InnoDB索引和MyISMA索引的区别
	a)主索引的区别:InnoDB的数据文件本身就是索引文件,而MyISMA的索引和数据是分开的
	b)辅助索引的区别:InnoDB的辅助索引data域存储相应记录

10. 索引的底层实现(B+树,为何不用红黑树,B树) 重点**
	红黑树:增加、删除时,红黑树会进行频繁的调整,来保证性质,费时
	B树(B-树):查询性能不稳定,查询结果高度不一致,每个节点保存指向真实数据的指针,相比B+树,每一层每个屋存储的元素更多,显得更高
	B+树:相较于其他两树,显得更矮更宽,查询层次更浅

11.	B+树的实现
	m阶B+树的特征:
	a)有k个子树的中间节点包含有k-1个元素(B树是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点中
	b)所有的叶子节点中包含了全部元素信息,及指向含这些元素记录的指针,且叶子节点本身依照关键字的大小 自小到大顺序连接
	c)所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(最小)元素

12. 为什么使用B+树
	索引查找过程中会产生磁盘IO消耗,主要看IO次数,和磁盘存取原理有关

13. 锁
	a)乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。乐观锁不能解决脏读的问题。 乐观:每次拿数据都认为别人不会修改,所以不上锁,但是更新的时候会判断一下在此期间别人有没有更新这个数据,可以使用版本号等机制。
	乐观锁适用于多读的应用类型,可以提高吞吐量。
	b)悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
	悲观,每次拿数据都认为别人会修改,所以每次都上锁,这样别人想拿这个数据就会阻塞,直到拿到锁。例如:行锁,表锁,读写锁等都是。
	f)共享锁(读锁):多个事务,只能读不能写,加lock in share mode
	c)排他锁(写锁):一个事务,只能写,其他事务不能读写,for update
	d)行锁:作用于数据行
	e)表锁:作用于表

14.	死锁解决
	找到进程号, kill 进程





MYSQL数据库优化----------------------20200908
1.MySQL版本
2.MySQL底层原理:逻辑分层,数据库引擎
3.SQL优化:sql优化和索引的关系
4.索引
5.SQL性能问题,优化方法
6.优化案例
7.避免索引失效(优化失效)的一些原则
8.一些其他优化方法
9.SQL排查-慢查询日志
10.分析海量数据
11.锁机制:解决因资源共享而造成的并发问题
12.主从复制


1.逻辑分层:连接层、服务层、引擎层、存储层
select     
连接层:提供与客户端连接的服务
服务层:提供各种用户使用的接口(select *)
		提供SQL优化器(MySQL Query Optimizer),优化器进行优化
引擎层:提供各种存储数据的方式(innoDB、MyISAM)
		 InnoDB(默认):事务优先,适合高并发操作,行锁
		 MyISAM:性能优先,表锁
存储层;存储数据

2.查询数据库引擎: 支持哪些引擎?  show engines;
	查看当前使用的引擎: show variables like '%storage_engine%';
	指定数据库对象的引擎: 
		create table tb(
			id int(4) auto_increment,
			name varchar(5),
			dept varchar(5),
			primary key(id)
		)ENGINE=MyISAM, AUTO_INCREMENT=1
		 DEFAULT CHARSET=utf8; 

3.SQL优化:
 	原因:性能低,执行时间太长、等待时间太长、sql语句太差(尤其连接查询)、索引失效、服务器参数设置不合理(缓冲区、线程数)

 	a. SQL编写过程:select dinstinct.. from .. join .. on .. where .. group by .. having .. order by .. limit

 		解析过程:from .. on .. join .. where.. group by .. having..select dinstinct..order by .. limit..
 		

 		文章:www.cnblogs.com/annsshadow/p/5037667.html

 	b.	SQL优化主要在于优化索引
 		索引:相当于书的目录
 		索引:关键字index是帮助高效获取数据的数据结构,索引是数据结构(树:B树、Hash树) MySQL是B+树
 		索引的缺点:
 			1.	索引本身很大,可以存储在内存/硬盘(通常在硬盘)
 			2.	索引不是所有情况都适合 (1)少量数据(2)频繁更新的字段(3)很少使用的列
 			3. 	索引可以提高查询效率,会降低增删改的效率
 		索引优点:
 			1. 	提高查询效率(本质是降低了IO的使用率)
 			2.	降低CPU使用率(.. order by , 加了索引本身已经排好序的结构,因此排序时候可直接使用,不需要排序CPU使用率就降低了)
 		3层B+树就可以存放上百万条数据,数据都放在叶子节点
 		B+树中查询任意的数据次数:n次(B+树的高度)

 4. 索引
 		分类:
 			单值索引:单列, 一个表可以有多个单值索引
 			唯一索引:唯一索引不能重复,(id)
 			复合索引:多列构成的索引(书的二级目录:找赵, 先找z,再zhao),不是必须同时用(最左匹配)

 		创建索引:
 			方式一:create 索引类型 索引名 on 表(字段)
 			单值索引: create index dept_index on tb(dept);
 			唯一索引: create unique index name_index on tb(name);
 			复合索引: create index dept_name_index on tb(dept, name);
 			方式二:alter table 表 add 索引类型 索引名(字段)
 			单值索引: alter table tb add index dept_index(dept);
 			唯一索引: alter table tb add unique index name_index(name);
 			复合索引: alter table tb add index dept_name_index(dept, name);

 			DDL语句会自动提交 commit;
 			注意:如果一个字段是主键,默认是主键索引(唯一索引且不为NULL)

 		删除索引:drop index 索引名 on 表名
 			drop index name_index on tb;

 		查询索引: show index from 表;

 5. SQL性能问题:
 		a.	分析SQL的执行计划:explain关键字,可以模拟SQL优化器执行SQL语句
 		b. 	MySQL查询优化器会干扰你们的优化

 		优化方法:官网(dev.mysql.com/doc/refman/5.5/en/optimization.html

 		explain select * from tb;

 		id:编号,大的优先查询
 		select_type:查询类型
 		table:表
 		type:类型
 		possible_keys:预测可能用到的索引
 		key:实际用到的索引
 		key_len:实际用到索引的长度
 		ref:表之间的引用
 		rows:通过索引查到的数据个数
 		Extra:额外的信息

 		准备数据:
 		create table course(
 			cid int(3),
 			cname varchar(20),
 			tid int(3)
 		);

 		create table teacher(
 			tid int(3),
 			tname varchar(20),
 			tcid int(3)
 		);

 		create table teacherCard(
 			tcid int(3),
 			tcdesc varchar(200)
 		);

 		insert into course values(1, 'java', 1);
 		insert into course values(2, 'html', 1);
 		insert into course values(3, 'sql', 2);
 		insert into course values(4, 'web', 3);

 		insert into teacher values(1, 'tz', 1);
 		insert into teacher values(2, 'tw', 2);
 		insert into teacher values(3, 'tl', 3);

 		insert into teacherCard values(1, 'tzdesc');
 		insert into teacherCard values(2, 'twdesc');
 		insert into teacherCard values(3, 'tldesc');

 		查询课程编号为2或教师证编号为3的老师信息

 		select t.* from teacher t, course c, teacherCard tc where t.tid=c.tid and t.tcid=tc.tcid and (c.cid=2 or tc.tcid=3);

 		(1)id值相同:从上往下顺序执行		t3-tc3-c4
 						teacher 插入三条后:tc3-c4-t6
 			表执行顺序因数量的个数改变而改变的原因:笛卡尔积
 							2 * 3 = 6 * 4 = 24
 							4 * 3 = 12 * 2 = 24	结果一样,中间不一样
 							数据小的表优先查询
 		(2)id值不同,越大越优先查询(本质:嵌套子查询时,先查内层)

 		查询教授sql课程老师的描述(desc)
 		explain select tc.tcdesc from teacherCard tc,teacher t, course c where tc.tcid = t.tcid and c.tid = t.tid and c.cname='sql';

 		将以上多表查询变为子查询形式:
 		explain select tc.tcdesc from teacherCard tc where tc.tcid = 
 		(select t.tcid from teacher t where t.tid = (select tid from course where cname = 'sql'));

 		explain select t.tname, tc.tcdesc from teacher t, teacherCard tc where t.tcid = tc.tcid and t.tid = (select c.tid from course c where cname = 'sql');

 		(3)id有相同又有不同:id值越大越优先,id值相同上到下顺序执行


 		select_type:
 			PRIMARY:包含子查询SQL中的主查询(最外层)
 			SUBQUERY:包含子查询的子查询(非最外层)
 			SIMPLE:简单查询(不包含子查询、union)
 			DERIVED:衍生查询(在查询时用到了临时表)
 					a.from子查询,有且只有一张表
 						select cr.cname from (select * from course where tid in (1, 2)) cr;
 					b.在from子查询中,如果table1 union table2,则table1是DERIVED, table2是union
 						select cr.cname from (select * from course where tid = 1 union select * from course where tid = 2) cr;
 			UNION:上例b.
 			UNION RESULT:告知开发人员哪些表之间存在union查询

 		table:查询的表


 		type:查询类型
 			system > const > eq_ref > ref > fulltext > ref_of_null > index_merge > unique_subquery > index_subquery > range > index > all;

 			企业常用: system > const > eq_ref > ref > range > index > all,要对type进行优化的前提,有索引!!
 			其中system,const理想情况,实际能达到ref>range

 		system:只有一条数据的系统表,或者 衍生表只有一条数据的主查询(偶尔)

 		增加索引:alter table test01 add constraint id_pk primary key(id);
 		explain select * from (select * from test01)[衍生表] where id = 1;

 		const:仅仅能查到一条数据的SQL,用户primary key 或者unique索引 

 		eq_ref:唯一性索引,对每个索引键的查询,返回匹配唯一行数据(每条有且只有一个,不能多,不能0) 
 			select .. from .. where name = ..  常见于唯一索引和主键索引

 			teacher tcid 加唯一索引, tc.tcid加主键索引
 			select t.tcid from teacher t, teacherCard tc where t.tcid=tc.tcid;

 			以上SQL,用到的索引是t.tcid,即teacher表中的tcid字段;如果teacher表的数据个数和连接查询的数据个数一致(这里都是三条),则有可能满足eq_ref;


 		ref:非唯一性索引,对于每个索引键查询,返回匹配的所有行(0,多个)

 			insert into teacher values(4, 'tz', 4);
 			insert into teacherCard values(4, 'tz44');

 			测试:
 			alter table teacher add index name_idx(tname);
 			select * from teacher where tname='tz';

 		range:检索指定范围的行,where后面是一个范围查询(between,in:有时候会失效,转为无索引ALL,>< >=)
 		select * from teacher where tid < 3; (tid in (1, 2))

 		index:查询全部索引中的数据
 			select tid from teacher; -- tid是索引

 		all:查询全部表中的数据
 			select cname from course; -- cname不是索引,需要扫描全表


 		总结:	system/const:结果只有一条数据
 				eq_ref:结果多条,但每条数据是唯一的
 				ref:结果多条,但每条数据是0条或者多条

 		possible_keys:可能用到的索引,预测的,可能不准
 		key:实际使用到的索引
 		key_len:索引的长度
 			name char(20), 若长度为0则索引没用,若为20则用了
 			作用:用于判断复合索引是否被完全使用

 			MySQL里面utf8一个字符占三个字节,gbk占两个字节,latin占一个
 			name char(20) not null   20*2=40
 			name1 char(20)           20*2+1=41	1个字节标识null
 			如果索引字段可以为null,则会用一个字节用于标识
 			drop index name1_idx on testkl;
 			增加复合索引:alter table testkl add index name_name1_idx(name, name1);
 			select * from testkl where name='';		--40
 			select * from testkl where name1='';		--81

 			varchar(20)	--可变长长度用2个字节标识
 			alter table testkl add column name2 varchar(20);
 			alter table testkl add index name2_idx(name2);
 			select * from testkl where name2 = ''; 	--43  20*2+1+2

 		ref:注意与type中的区分,作用:指明当前表所参照的字段
 			select .. where a.c = b.x(引用b的x); (其中b的x可以是常量const)
 			select * from course c, teacher t where c.tid=t.tid and t.tname='tw';

 		rows:被索引优化查询的数据个数
 			select * from course c, teacher t where c.tid = t.tid  and t.tname = 'tz';

 		Extra:
 		using filesort(出现,标识性能消耗大,需要‘额外’的一次排序(查询)),常见于order by语句中。

 			create table test02(
 				a1 char(3),
 				a2 char(3),
 				a3 char(3),
 				index idx_a1(a1),
 				index idx_a2(a2),
 				index idx_a3(a3)
 			);
 			select * from test02 where a1 ='' order by a1;
 				查完之后排序,正常
 			select * from test02 where a1 ='' order by a2;出现filesort
 				查完a1,根据a2排,先查了a2在排序,所以多一次
 			小结:对于单索引,如果排序和查询是同一字段,不会出现filesort
 				避免:where哪些字段就obder by字段

 			复合索引:原则不能跨列(最佳左前缀)
 				alter table test02 add index idx_a1a2a3(a1, a2, a3);
 				select * from test02 where a1='' order by a3;	(跨了a2,出现filesort)
 				select * from test02 where a2='' order by a3;	(跨了a1)
 				select * from test02 where a1='' order by a2;	(没有filesort)
 				小结:避免,where和order by按照复合索引的顺序使用,不要跨列和乱序使用

 		using temporary:性能损耗大,用到了临时表。一般出现在group by语句中
 			select a1 from test02 where a1 in ('1','2','3') group by a1;
 			select a1 from test02 where a1 in ('1','2','3') group by a2;(出现)  要按a2分组

 			避免:查哪些列就用哪些列分组
 			解析过程:from  on join where groupby having select order by limit


 		using index:性能提升,索引覆盖(覆盖索引)。不读取源文件,只从索引文件中获取数据,只要使用到的列都在索引里(不需要回表查询),就是索引覆盖using index
 			对possible_keys和key有影响,有where两者都有,否则key里有
 			select a1,a2 from test02 where a1='' or a2='';
 			select a1,a3 from test02 where a1='' or a3='';

 		using where(需要回原表查询)

 		impossible where:where语句永远false

 		using join buffer:作用,MySQL引擎使用了连接缓存

 	create table test03(
 		a1 int(3) not null,
 		a2 int(3) not null,
 		a3 int(3) not null,
 		a4 int(3) not null,
 		index idx_aaaa(a1, a2, a3, a4)
 	);

 	select a1,a2,a3,a4 from test03 where a1=1 and a3=3 and a4=4;
 	a1有效,跨a2,所以a3,a4索引失效,需回表查using where

 	where和order by拼起来看是否跨列,如果跨列则using filesort;

 	总结:(1)如果复合索引和使用的顺序全部一致,则复合索引全用,若部分一致(且不跨列使用),则使用部分索引
 		(2)where和order by拼起来,不要跨列使用


 	优化示例:
 	1.单表优化:
 		(1)索引不能跨列使用(最佳左前缀),保持索引的定义和使用的顺序一致性
 		(2)逐步优化
 		(3)将含in的范围查询,放到where最后,防止索引失效

 	2.两表优化
 		(1)小表驱动大表,索引建立在经常使用的字段
 				where 小表.ID = 大表.ID
 				.. on t.id = c.id将数据量小的表放左边

 	3.三表优化:
 		(1)小表驱动大表
 		(2)索引建立在常用的字段上

 	避免索引失效的一些原则:
 		(1)复合索引,不要跨列或无序使用(最佳左前缀)
 		(2)尽量使用全索引匹配
 		(3)不要再索引上进行任何操作(计算,函数,类型转化)
 				select .. where A.x*3=..;
 		(4)索引不能使用不等于(!= <>)或者is (not) null,否则自身以及右侧失效
 		(5)复合索引中有>号,失效

 		SQL优化是一种概率层面的优化
 		(6)一般情况,范围查询(< > in)索引,本身有用,之后的失效
 		(7)补救,尽量使用覆盖索引
 			select a,b,c from xx where a=.. and b=..
 		(8)like尽量以“常量”开头,不要以‘%’开头,否则索引失效
 				like ”1%“   like ”%1%“,  
 				如果必须like %1%, 可以使用索引覆盖挽救一部分
 				select name from .. where name like "%1%";
 		(9)尽量不要类型转换(显式、隐式),索引失效
 		(10)尽量不使用or,索引失效,左边的也干掉了


 	一些其他的优化u方法:
 		(1)exist,in
 			如果主查询数据集大,使用in,否则exist效率高
 		(2)order by优化
 			using filesort:有两种算法(双路排序、单路排序)根据IO次数
 			MySQL4.1之前默认双路:扫描两次磁盘(1.从磁盘读取排序字段,对排序字段进行排序(再缓存区中排序)  2.扫描其他字段)
 			MySQL4.1之后默认单路(IO消耗性能):一次读取全部字段,在buffer中进行排序,但单路排序会有一定隐患(有可能多次IO)数据量太大,缓存区容量不足,无法一次性读完,因此会”分片读取、多次读取“。
 			单路比双路占用更多buffer,单路排序如果数据大,可以考虑调大buffer的容量大小:set max_length_for_sort_data = 1024;
 			如果max_length_for_sort_data值太低,MySQL自动从单路->双路(太低:需要排序的列总大小超过了定义的字节数)

 				a.选择单路、双路,调整buffer容量大小
 				b.避免select *, 不索引覆盖了 
 				c.复合索引,不跨列,避免using filesort
 				d.保证排序字段的排序一致性,全升、全降



 	SQL排查:
 		慢查询日志:MySQL提供的一种日志记录,用于记录响应时间超过阈值的SQL语句(long_query_time,默认10秒)
 		慢查询日志默认关闭,建议:调优时打开,最终部署时关闭

 		检查是否开启了慢查询日志: show variables like '%slow_query_log%';
 		临时开启:set global slow_query_log = 1; --在内存中开启
 		重启mysql服务恢复默认 service mysql restart;
 		
 		临时设置阈值:set long_query_time=10;完毕后重登起效

 		show global status like '%slow_queries%';


单值索引、和复合索引举例
索引失效的原理:
	like失效原理
	or失效原理
	复合索引失效原理

讲讲平衡二叉树、B树、B+树
	B+树:双向链表

InnoDB是聚簇索引,MyISAM是非聚簇索引

索引查找流程


在这里插入图片描述
在这里插入图片描述

索引查找流程

在这里插入图片描述

在这里插入图片描述

索引失效原理

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值