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')



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













innodb myisa
truncate和delete

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字的后面,现在
用一个简单的示意图来大概说明一下在数据库中的样子:

屏幕快照 2020-04-18 下午2.07.38
注:第一列的地址表示该行数据在磁盘中的物理地址,后面三列才是我们SQL里面用的表里的列,其中id是主键,建立了聚集索引。


结合上面的表格就可以理解这句话了吧:数据行的物理顺序与列值的顺序相同,如果我们查询id比较靠后的数据,那么这行数据的地址在磁盘中的物理地址也会比较靠后。而且由于物理排列方式与聚集索引的顺序相同,所以也就只能建立一个聚集索引了。

ps:基本语法


创建:ALTER mytable ADD  [UNIQUE ]  INDEX [indexName] ON (columnname(length))

删除:DROP INDEX [indexName] ON mytable;

查看:SHOW INDEX FROM table_name

非聚集索引

定义:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。
其实按照定义,除了聚集索引以外的索引都是非聚集索引,只是人们想细分一下非聚集索引,分成普通索引,唯一索引,全文索引。如果非要把非聚集索引类比成现实生活中的东西,那么非聚集索引就像新华字典的偏旁字典,他结构顺序与实际存放顺序不一定一致。

非聚集索引的二次查询问题

非聚集索引叶节点仍然是索引节点,只是有一个指针指向对应的数据块,此如果使用非聚集索引查询,而查询列中包含了其他该索引没有覆盖的列,那么他还要进行第二次的查询,查询节点上对应的数据行的数据。

如有以下表t1:
屏幕快照 2020-04-18 下午2.19.08
以及聚集索引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手动)类型转换),会导致索引失效而转向全表扫描
![-w872](../media/15873806172988.jpg)

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

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.页锁

posted @ 2020-05-15 17:36  lanvce  阅读(175)  评论(0)    收藏  举报
//小火箭