mysql高级部分学习

学习尚硅谷的mysql高级视频的笔记。

1、mysql的配置文件。

在windows中是my.ini文件:

1)、log-bin:表示主从复制的日志文件,用于主从复制。

2)、log-error="SO3JFYNN8EW6GMO.err":表示错误日志。

3)、server-id=1:表示本机的序号为1。

4)、datadir=D:/mysql5.7/Data:存放数据库信息的目录,

2、mysql的架构从上到下分成四层:
1)、连接层:连接处理,授权认证,相关的安全方案。

2)、服务层:完成sql的优化,分析,缓存等功能。

3)、引擎层:负责存储和提取数据。

4)、存储层:数据存储层,主要将数据存储在文件系统之中,并完成与引擎的交互。

3、mysql引擎

1)查看使用的引擎:

show engins或者show

MYISAM和INNODB的比较

不支持主外键值对;支持

不支持事务;支持

表锁,不适合高并发;行锁,适合高并发

只缓存索引;缓存索引和数据,对内存要求更高

表空间小;表空间大

关注点在性能,更多情况下适合查询多的情况;关注点事务。

4、mysql性能优化下降原因

1)、查询语句写的烂

2)、索引失效

        单值索引             

                create  index  idx_user_name   on user(name)

        复合索引

                create  index  idx_user_name_email  on user(name,email)

3)、查询有太多的join

4)、服务器调优及各个参数

5、mysql的执行顺序 

         机器从from开始读。

 1)、内连接

          select  *from  tableA  A  inner join  tableB B  on  A.key=B.key。

2)、左外连接

          select  *from  tableA  A   left  join   tableB B  on A.key= B.key

          当b没有的,用null补全。

3)、右外连接

          select   *from  tableA   A   right  join   tableB  B  on   A.key=B.key

          当a没有时,用null补全

4)、左外连接,去除右表部分

          select   *from  tableA  A    left  join    tableB  B   on   A.key=B.key  where   B.key is null

           a的独有,这此时b的用null补齐,所以此时b是为空的。

5)、右外连接,去除左表部分

           select  *from  tableA A  right  join  tableB  B   on A.key = B.key  where A.key  is null

6)、全连接(可以采用两者相加)union 可以组合并去重

          select   *from tableA A left join tableB B   on   A.key=B.key  union

           (select *from tableA  A  right join tableB B )

7)、中心空出来

 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)

6、什么是索引

1)、索引是一种数据结构,在于提高查找效率。

        排好顺序的快速查找数据结构。

 数据库维护着满足特定算法的数据结构,这种数据结构以

某种方式指向数据,这样可以在这些数据结构上实现高级的超找

算法,这种数据结构称为索引。 

 BTREE索引(没有特殊指定的情况下)

频繁删改的字段,不适合建索引。

2)、优势

提高数据检索的效率,降低数据库的io成本

通过索引列对数据进行 排序,降低数据排序的成本,降低了cpu的消耗

3)、劣势

索引也是一张表,占磁盘空间。

更新表时要维护索引,会降更新效率。

索引只是一个提高效率的因素,建立索引需要花时间和精力。

4)、单值索引,只包含一个列,一张表可以有多个单值索引。

5)、唯一索引,索引列的值必须唯一,允许为空。

6)、复合索引,包含多个列。

 7)、索引的相关操作

create   index  idx_user_name on user(name)

alter  user  add index  idx_user_name on (name)

show index from user

drop index idx_user_name on user

8)、索引结构

Hash索引

full-text全文索引

R-Tree 索引

BTree索引 :

6、哪些情况要创建索引。

1)、主建自动建立唯一索引

2)、频繁作为查询条件的字段应该创建索引

3)、查询中与其他表关联的字段,外建关系建立索引。

4)、频繁更新的字段,不适合创建索引

5)、where条件里用不到的字段补创建索引。

6)、单建或者组合索引的选择问题,在高并发下倾向于创建复合索引

7)、查询中排序的字段,排序的字段如果按照索引去访问,将提高效率

8)、查询中统计或者分组字段

7、哪些情况不需要创建索引

1)、表记录太少

2)、经常增删的表

3)、数据重复且分布平均的字段。

8、性能分析:

mysql query optimizer

常见瓶颈:

cpu负担重:一般发生在数据装入内存和磁盘重读取数据的时候。

io负担重:装入数据远远大于内存容量时。

服务器硬件的性能瓶颈

explain:执行计划

怎么玩:explain+SQL

能干嘛:

1)能够查看表的读取顺序。

2)数据读取操作的操作类型。

3)哪些索引可以使用,

4)哪些索引被实际使用

5)表之间的引用

6)每张表有多少行被优化器查询。

explain+SQL的执行结果的头部

id:相同:则查询的顺序一样,为table中的从上到下。

如果id不同:id越大,则比较先查询。

derived2:表示衍生的虚表,其中2表示id为2的那张表。

select_type:主查询或者子查询或者简单查询

                 simple:不包含子查询或者union查询

                 primary、subquery、derived(临时)、union、

                 union-result 合并的结果集

table:显示关于哪张表

type:访问类型

       system>const>eq_ref> ref> range>index>all

      一般来说,得保证查询至少带到range级别,最好能达到ref.

       system:表只有一行记录(等于系统表)。

       const:表示通过检索一次就找到了,const用于

       比较主建或者唯一索引,将查询放入where查询。

  eq_ref:唯一性索引扫描,对于每个索引建,表中只有一条记录

  与之匹配。常用与主建或者唯一索引的扫描。

  ref:非唯一性索引扫描,会返回某个单独值的所有行。

  range:只检索给定的范围。一般时where语句中加了

  between and < >等范围的限制。

  index:也是全表扫描,只不过是对索引的索引树进行扫描。

  从索引中拿,而all从数据中拿。

  all:全表扫描。

possible_keys:表中可能运用的索引,但不一定使用

key:实际使用的索引。若查询中使用了覆盖索引则该索引仅仅出现在

key列表中。

覆盖索引:建立的索引和查询的字段顺序和个数匹配。

key_len:索引字段的最大可能长度,并非实际使用长度。精度越大,则

长度越大。同样的结果下,key_len小好。

ref:在type为ref或者eq_ref级别时,所引用到的字段或者常量。

rows: 表中有多少被优化器查询。

extra:十分重要的而外信息。

        using filesort:mysql无法用索引排序的排序为文件内排序。

        已经建立了复合索引:idx_col1col2col3

      (select col1 from t1 where col1='ac' order by col3)

       using temporary:产生了临时表。常见了order by 或者 

       group by

       (select col1 from t1 where col1 in('ac','ab')  group by col3 )

        正确:(select col2 from t1 where col1 in('ac','ab')  group by col2,col3)

        using index:使用了覆盖索引。如果有using where 表示用于查找,如果

         没有则只用于从索引中读取数据。

         覆盖索引:select的数据列只从索引中就能够取得,不必读取数据行。换句话说

         就是查询列要被所建的索引覆盖。

using where:使用了where条件

using join buffer:使用了连接缓存。

impossible where:where 后面的语句总是为false。

select tables optimized away:在没有groupby的情况,基于索引优化min或者max操作。

distinct:优化distinct操作。找到第一个匹配的记录后就完成。

9、实际的案例知识总结:

1)建立复合索引后A_B_C,B字段范围以后的索引会失效,此时C进行了orderby的操作。

如果不合理,则删除索引。这次直接建立A_C索引,可以起作用。

2)两表之间的索引问题

左外连接要将索引建立在右表中,右外连接要将索引建立在左表中。

3)三表之间的问题

  跟2)中一样,但是要注意:永远用小表驱动大表

   优先优化内层的循环。

    保证join条件已被索引。     

10、索引失效问题

1)复合索引中全局匹配最好,也可以部分满足。 

2)最佳左前缀法则

3)对索引的列不能进行操作,比如类型转换,函数处理等

4)范围之后的索引会失效

5)尽量使用覆盖索引,此时中间的某个索引如果使用范围的花化,type也为ref,key_len变小。(如果查询的字段被复合索引包含)

6)在使用不等于<>会使索引失效。

7)is null 或者is not null也无法使用索引

8)like 中如果开头为“%xxx",会导致索引失效,放在右边较好,但是type应该为range

     如果硬是要两边加%怎么办:使用覆盖索引来解决。

9)字符串不加单引号,会使得索引失效。varchar类型不能失去单引号。

10)少用or,用它会使得索引失效。

11、建立了idx_abcd  则查询的时候,不管是a、b、c、d还是其他顺序,mysql会进行相关的优化。

select * from user where a=1 and b=1 and d=1 order by c(没有filesort)

(c也是用到了,但不是用于查询,而是用于排序,但没有统计到explain中)

 select *from user where a=1 and b=1 order by d(这里排序是会出现file sort)

 select *from user where a=1 and d=1 order by b,c(查询只用到一个索引,b、c用于排序,所以没有出现filesort)

select *from user where a=1 and d=1 order by c、b(出现了filesort)

select *from user where a=1 and b=1 and d=1 order by c、b(查询用到两个索引,order by c b=1),因为b=1是固定

的,所以不用进行排序。

select *from user where a=1  and d=1 group by c、b(分组之前必排序)出现filesort temporary(临时表)

select *from user where a=1 and b=1 and c like "1%" and d 用到所有

12、小表驱动大表

1)跑一天,查看查询状况,开启满查询日志,抓取对应的sql语句。

2)explain + sql

3) show profile(查看执行周期和细节)

4)mysql数据库的参数调优。

select *from a where id in (select id from b)

当b表小于a表时,用in要优于exists

select *from a exists (select 1 from where b.id=a.id)

13、使用order by

select *from a where age >20 order by age

不会出现filesort情况

select *from a where age > 20 order by birth

会出现filesort情况

select *from a where age > 20  order by brith,age

会出现filesort的情况

select *from a where  age >20 order by age asc,birth desc

filesort: 单路排序:一次磁盘的扫描(现在某认的选项)sort_buffer中,如果不够,效率反而比较低和两路排序:对磁盘有两次扫描

oderby中三大方案:

避免使用select *(容易把sort_buffer_size用满)

如果超过了,会产生临时文件自行合并,导致多次io

尝试提高sort_buffer_size

尝试提高max_length_sort_data

orderby :后面要么全部升,要么全部降

order b y a = const order b ,c

order by a=const and b>const order by b,c(可以使用)


group by 是先排序再分组,where高于having,能在where中完成的就不要在having中

14、慢查询日志

慢查询日志是mysql提供的一种日志记录,超过long_query_time会被记录到日志中。默认为10秒

默认情况下,是没有开启的,需要手动开启。查看:show variables like "%slow_query_log%";

set global slow_query_log=1

show varables like "%slow_query%"

mysqldownslow是分析的一个工具。

15、批量插入

log_bin_trust_function_creator参数的开启

随即产生字符串的函数:

delimiter $$

create function random(n int) returns varchar(255)

begin

 declare char_str varchar(100) default ''cjhcjhcjh;

 return char_str;

end $$ 

存储过程:

16、show profile

可以用来分析当前语句执行的资源消耗情况。

show global varables like ""%profiling;

有三个属性:

query_id:查询的id

duration:持续的时间

query:查询的语句

show profile cpu,block io for query 3

对某条语句进行解析。如果出现:

converting heap to myisam:查询结果太大,内存不够

create temp table:创建临时表

copying temp to the disk:将临时表拷贝到硬盘中,危险

locked:出现锁的状况。

17、全局查询日志(只允许在测试环境中用)

show varables like "general_log";

set general_log=1;

set global log_output="table":以表的形式

则会把查询语句存入到mysql数据库的general_log表中,系统自带的数据库。、

18、mysql的锁:行锁、表锁(读锁、写锁)

show open  tables(查看是否加了锁)

上锁:lock table a read,b write

unlock tables;解锁所有的表

加了读锁的表的session不可以写自己,不可以操作别人。(加了锁要清帐,才可以取操作其他的)

在别的session,可以读被锁的表和其他表,不可以写被锁的表,此时会处于阻塞状态。

加了写锁后,不可以操作其他表,可以对锁的表进行读和写

在别的session中只能操作其他表,对写锁的表,都处于阻塞状态。

show status like "table%"

table_locks_wait:锁等待的次数。

myisam 比较适合读为主的项目,写锁太多会造成阻塞。

行锁:

支持更高的并发量

innodb:支持事务,支持行锁。

事务的隔离级别:

读未提交

读已提交

可重复读

串行化

show variables like "%tx_isolation":

读己之所写,

强一致型(现实可能不太理想)c,高可用(a表示高可用)

某一行被update没有提交,本session可以看到更新;

其他session看不到更新,如果更新该行将会被阻塞。

当对应的session自动提交被禁止后,要想看到别的session的提交结果,要先commit下才可以看到

索引失效:会导致行锁变成表锁。

 update user set username=100 where id=1;

则此时在另外一个session中该表会被锁主。

update  tableA set name=2000(name为varchar类型,这样 会导致索引失效)

间隙锁:用范围的条件时,会对范围的记录上锁。尽管范围了没有某一条记录,也会加上锁。

会导致阻塞。

比如:update user set age=12 where id >1 and id <10

则另外一个session将无法对id为2到9的行进行操作,不管该行是否存在。

面试题目:锁定某一行

select * from user where id=8 for update;

show status like 'innodb_row_lock%';

猜你喜欢

转载自blog.csdn.net/chenjianhuideyueding/article/details/79517628