mysql笔记
mysql基础部分








中间补充
mysql获取系统时间
1.获取单个年月日
获取当前系统日期时间:select SYSDATE() AS 系统日期时间;
获取当前系统年月日:select current_date AS 年月日;
获取当前系统年份:select year(CURRENT_DATE) AS 年 ;
获取当前系统月份:select month(CURRENT_DATE) AS 月;
获取当前系统日:select day(CURRENT_DATE) AS 日;
获取当前系统时间:select time(SYSDATE()) AS 系统时间
获取当前系统小时:select HOUR(SYSDATE()) AS 系统小时;
获取当前系统分钟:select MINUTE(SYSDATE()) AS 系统分钟;
获取当前系统秒:select SECOND(SYSDATE()) AS 系统秒;
获取当前系统毫秒:select MICROSECOND(SYSDATE()) AS 系统秒;
Mysql数据库中获取系统时间,年,月,日单个获取
2.获取当前时间,格式为YYYY-MM-DD HH:mm:ss
三种方法:
1. select now();//2020-03-21 16:55:03
2. select sysdate();//2020-03-21 16:55:03
3.select current_timestamp();//2020-03-21 16:55:03
这些方法后面加0 如:
select now()+0 ;//20200321165503
3.获取当前年月日
1.select current_date();//2020-03-21
2.select curdate();//2020-03-21
4.获取时分秒
1.select current_time();//16:59:49
2.select curtime(); //16:59:49
5、获取当前时间的秒数
格林尼治时间为:1970-01-01 00:00:00,此时位为东八区的北京时间为:1970-01-01 08:00:00
select unix_timestamp;//也就是获取相对于格林尼治时间的秒数
6.获取指定时间的秒数
select unix_timestamp('1979-01-01 09:00:00');//结果是3600 因为取得标准时当地北京时间
7.获取指定秒数的时间
// 1979-01-01 09:00:00
select unix_timestamp('3600');
8.获取两时间之间制订单位的时长
格式:
SELECT TIMESTAMPDIFF(单位,时间1 ,时间2);//默认是后面减去前面
ps:
SELECT TIMESTAMPDIFF(DAY,'2020-10-19 18:00:00 ','2020-10-20 18:00:00')



等值连接与自然连接
外连接:
















Mysql高级
1.概念:MySQL官方对索引的定义为:索引(Index)是帮助MySQL高校获取数据的数据结构。
可以得到索引的本质:索引是数据结构 底层是B+树

2.优缺点:
优点:1.类似大学图书馆建书目索引,提高数据检索效率,降低数据库的IO成本
2.通过索引列对数据进行排序,降低数据排序成本,降低了CPU的消耗
3.在使用分组和排序子句进行数据检索时,可以减少查询中分组和排序的时间
缺点:1.实际上索引也是一张表,该表保存了主键和索引字段,并指向实体表的记录,所以索引列也是要占用空间的
2.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如果对表INSERT,UPDATE和DELETE。因为更新表时,MySQL不
仅要不存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息
3.索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立优秀的索引,或优化查询语句
3.索引分类
1.主键索引(聚集)
设定为主键后数据库会自动建立索引,innodb为聚集索引
2.普通(单列索引、单值索引)索引
即一个索引只包含单个列,一个表可以有多个单列索引
3.唯一索引
索引列的值必须唯一,但允许有空值
4.复合索引
即一个索引包含多个列
在数据库操作期间,复合索引比单值索引所需要的开销更小(对于相同的多个列建索引)
当表的行数远大于索引列的数目时可以使用复合索引
聚集(clustered)索引与非聚集索引
聚集索引
定义:数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。
单单从定义来看是不是显得有点抽象,打个比方,一个表就像是我们以前用的新华字典,聚集索引就像是拼音目录,而每个字
存放的页码就是我们的数据物理地址,我们如果要查询一个“哇”字,我们只需要查询“哇”字对应在新华字典拼音目录对应的
页码,就可以查询到对应的“哇”字所在的位置,而拼音目录对应的A-Z的字顺序,和新华字典实际存储的字的顺序A-Z也是一
样的,如果我们中文新出了一个字,拼音开头第一个是B,那么他插入的时候也要按照拼音目录顺序插入到A字的后面,现在
用一个简单的示意图来大概说明一下在数据库中的样子:

注:第一列的地址表示该行数据在磁盘中的物理地址,后面三列才是我们SQL里面用的表里的列,其中id是主键,建立了聚集索引。
结合上面的表格就可以理解这句话了吧:数据行的物理顺序与列值的顺序相同,如果我们查询id比较靠后的数据,那么这行数据的地址在磁盘中的物理地址也会比较靠后。而且由于物理排列方式与聚集索引的顺序相同,所以也就只能建立一个聚集索引了。
ps:基本语法
创建:ALTER mytable ADD [UNIQUE ] INDEX [indexName] ON (columnname(length))
删除:DROP INDEX [indexName] ON mytable;
查看:SHOW INDEX FROM table_name
非聚集索引
定义:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。
其实按照定义,除了聚集索引以外的索引都是非聚集索引,只是人们想细分一下非聚集索引,分成普通索引,唯一索引,全文索引。如果非要把非聚集索引类比成现实生活中的东西,那么非聚集索引就像新华字典的偏旁字典,他结构顺序与实际存放顺序不一定一致。
非聚集索引的二次查询问题
非聚集索引叶节点仍然是索引节点,只是有一个指针指向对应的数据块,此如果使用非聚集索引查询,而查询列中包含了其他该索引没有覆盖的列,那么他还要进行第二次的查询,查询节点上对应的数据行的数据。
如有以下表t1:

以及聚集索引clustered index(id), 非聚集索引index(username)。
使用以下语句进行查询,不需要进行二次查询,直接就可以从非聚集索引的节点里面就可以获取到查询列的数据。
select id, username from t1 where username = '小明'
select username from t1 where username = '小明'
但是使用以下语句进行查询,就需要二次的查询去获取原数据行的score:
select username, score from t1 where username = '小明'
如何解决非聚集索引的二次查询问题
复合索引(覆盖索引)
建立两列以上的索引,即可查询复合索引里的列的数据而不需要进行回表二次查询,如index(col1, col2),执行下面的语句:
select col1, col2 from t1 where col1 = '213';
要注意使用复合索引需要满足最左侧索引的原则,也就是查询的时候如果where条件里面没有最左边的一到多列,索引就不会起作用。
总结与使用心得
1.使用聚集索引的查询效率要比非聚集索引的效率要高,但是如果需要频繁去改变聚集索引的值,写入性能并不高,因为需
要移动对应数据的物理位置。
2.非聚集索引在查询的时候可以的话就避免二次查询,这样性能会大幅提升。
3.不是所有的表都适合建立索引,只有数据量大表才适合建立索引,且建立在选择性高的列上面性能会更好。
4.最左原则(针对复合索引)
1.简单说下什么是最左匹配原则
顾名思义:最左优先,以最左边的为起点任何连续的索引都能匹配上。同时遇到范围查询(>、<、between、like)就会停止
匹配。
例如:b = 2 如果建立(a,b)顺序的索引,是匹配不到(a,b)索引的;但是如果查询条件是a = 1 and b = 2或者a=1(又
或者是b
= 2 and b = 1)就可以,因为优化器会自动调整a,b的顺序。再比如a = 1 and b = 2 and c > 3 and d = 4 如果
建立(a,b,c,d)顺序的索引,d是用不到索引的,因为c字段是一个范围查询,它之后的字段会停止匹配。
2.最左匹配原则的原理
最左匹配原则都是针对联合索引来说的,所以我们有必要了解一下联合索引的原理。了解了联合索引,那么为什么会有最左匹
配原则这种说法也就理解了。
我们都知道索引的底层是一颗B+树,那么联合索引当然还是一颗B+树,只不过联合索引的健值数量不是一个,而是多个。构建一颗B+树只能根据一个值来构建,因此数据库依据联合索引最左的字段来构建B+树。
例子:假如创建一个(a,b)的联合索引,那么它的索引树是这样的

可以看到a的值是有顺序的,1,1,2,2,3,3,而b的值是没有顺序的1,2,1,4,1,2。所以b = 2这种查询条件没有
办法利用索引,因为联合索引首先是按a排序的,b是无序的。
同时我们还可以发现在a值相等的情况下,b值又是按顺序排列的,但是这种顺序是相对的。所以最左匹配原则遇上范围查询
就会停止,剩下的字段都无法使用索引。例如a = 1 and b = 2 a,b字段都可以使用索引,因为在a值确定的情况下b是相
对有序的,而a>1 and b=2,a字段可以匹配上索引,但b值不可以,因为a的值是一个范围,在这个范围中b是无序的。
5.索引使用场景
适合建索引:
1.主键自动建立唯一索引
2.频繁作为查询的条件的字段应该创建索引
3.查询中与其他表关联的字段,外键关系建立索引
4.频繁更新的字段不适合创建索引 因为每次更新不单单是更新了记录还会更新索引,加重IO负担
5.Where条件里用不到的字段不创建索引
6.单列/组合索引的选择问题,who?(在高并发下倾向创建组合索引)
7.查询中排序的字段,排序字段若通过索引去访问将大大提高排序的速度
8.查询中统计或者分组字段
并不需要索引:
1.表记录太少
2.经常增删改的表
3.数据重复且分布平均的表字段,因此应该只为经常查询和经常排序的数据列建立索引。
注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
6.索引优化
EXPLAIN关键字
可以模拟优化器执行SQL语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是结构的性能瓶颈
语法:EXPLAIN+sql语句
字段包含信息

id:
id越大,优先级越高,先执行,id相同,顺序执行
select_type:
分类

1.SIMPLE 简单的select查询,查询中不包含子查询或者UNION
2.PRIMARY 查询中若包含任何复杂的子部分,最外层查询则被标记为
3.SUBQUERY 在SELECT或者WHERE列表中包含了子查询
4.DERIVED 在FROM列表中包含的子查询被标记为DERIVED(衍生)
MySQL会递归执行这些子查询,把结果放在临时表里。
5.UNION 若第二个SELECT出现在UNION之后,则被标记为UNION;
若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED
6.6.UNION RESULT 从UNION表获取结果的SELECT
table:
显示这一行的数据是关于哪张表的
type:
分类

1.system 表只有一行记录(等于系统表),这是const类型的特例,平时不会出现,这个也可以忽略不计
2.const 表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为只匹配一行数据,所以很
快。如将主键至于where列表中,MySQL就能将该查询转换为一个常量
3.eq_ref 唯一性索引,对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描
4.ref 非唯一索引扫描,返回匹配某个单独值的所有行。
本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,
它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体
5.range 只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引
一般就是在你的where语句中出现了between、<、>、in等的查询
这种范围扫描索引扫描比全表扫描要好,因为他只需要开始索引的某一点,而结束语另一点,不用扫描全部索引
6.index Full Index Scan,index与ALL区别为index类型只遍历索引树。这通常比ALL快,因为索引文件通常比数据
文件小。(也就是说虽然all和index都是读全表,但index是从索引中读取的,而all是从硬盘中读的)
7.all FullTable Scan,将遍历全表以找到匹配的行
possible_key:
显示可能应用在这张表中的索引,一个或多个。
查询涉及的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用
key:
实际使用的索引。如果为null则没有使用索引
查询中若使用了覆盖索引,则索引和查询的select字段重叠
key_len:
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。在不损失精确性的情况下,长度越短越好
key_len显示的值为索引最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的
ref:
显示索引那一列被使用了,如果可能的话,是一个常数。那些列或常量被用于查找索引列上的值
rows:
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数
Extra:
1.Using filesort 说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL中无
法利用索引完成排序操作成为“文件排序”
2.Using temporary 使用了临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序order
3.USING index 表示相应的select操作中使用了覆盖索引(Coveing Index),避免访问了表的数据行,效率不错!
如果同时出现using where,表明索引被用来执行索引键值的查找;
如果没有同时出现using where,表面索引用来读取数据而非执行查找动作。
4.using where 表面使用了where过滤
5.using join buffer 使用了连接缓存
6.impossible where where子句的值总是false,不能用来获取任何元组
7.select tables optimized away 在没有GROUPBY子句的情况下,基于索引优化MIN/MAX操作或者对于MyISAM存
储引擎优化COUNT(*)操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。
8.distinct 优化distinct,在找到第一匹配的元组后即停止找同样值的工作
索引分析
单表 多表 连接查询 要把索引建立在相反的一边 比如 left join 就把索引建立在右表中

索引失效
1.全值匹配我最爱
2.最佳左前缀法则
3.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描

4.存储引擎不能使用索引中范围条件右边的列
5.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select*

6.mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描
7.is null,is not null 也无法使用索引
8.like以通配符开头('$abc...')mysql索引失效会变成全表扫描操作
问题:解决like'%字符串%'索引不被使用的方法??
1、可以使用主键索引
2、使用覆盖索引,查询字段 必须是建立覆盖索引字段
3、当覆盖索引指向的字段是varchar(380)及380以上的字段时,覆盖索引会失效!
9.字符串不加单引号索引失效
10.少用or,用它连接时会索引失效

上面倒数第四个是以常量开头,索引用到了b索引,但是type 是range
上面倒数第三、第二以%开头 无法确定 索引直接没被使用 只使用了a索引 所以type显示ref

注意:
1.定值、范围还是排序,一般order by是给个范围 索引本来就有排序功能
所以会使用到索引 但要注意到多字段排 序 看是不是符合索引的顺序
2.group by 基本上都需要进行排序 using filesort ,会有临时表产生 using tempoary
建议:
对于单键索引,尽量选择针对当前query过滤性更好的索引
在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠左越好
在选择组合索引的时候,尽量选择可以能包含当前query中的where子句中更多字段的索引
尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的
7.查询优化

小表驱动大表

Order by 分析:


8.慢查询日志







9.show profiles
是mysql提供可以用来分析当前会话中语句执行的资源消耗情况。可以用于SQL的调优测量




mysql锁

1.表锁
特点:
偏向MyISAM存储引擎,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发最低

读锁:


写锁:

结论:

表锁分析:

2.行锁
偏向InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁
更新丢失:

脏读:

不可重复读:

幻读:

事务隔离级别:

演示:


无索引行锁升级为表锁:varchar 不用 ' ' 导致系统自动转换类型, 行锁变表锁
间隙锁:

常见面试题:如何锁定一行:

结论:

行锁分析:

优化建议

3.页锁


浙公网安备 33010602011771号