MySQL掌握70点

Posted gosling9527

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL掌握70点相关的知识,希望对你有一定的参考价值。

001、数据库水平拆分和垂直拆分

一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面。

优点:

       1. 拆分后业务清晰,拆分规则明确。

       2. 系统之间整合或扩展容易。

       3. 数据维护简单。

缺点:

       1. 部分业务表无法join,只能通过接口方式解决,提高了系统复杂度。

       2. 受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高。

       3. 事务处理复杂。


相对于垂直拆分,水平拆分不是将表的数据做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中 的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,主要有分表,分库两种模式。

优点:

       1. 不存在单库大数据,高并发的性能瓶颈。

       2. 对应用透明,应用端改造较少。   

       3. 按照合理拆分规则拆分,join操作基本避免跨库。

       4. 提高了系统的稳定性跟负载能力。

缺点:

       1. 拆分规则难以抽象。

       2. 分片事务一致性难以解决。

       3. 数据多次扩展难度跟维护量极大。

       4. 跨库join性能较差。

002、B+树的结构

003、索引添加原则

1、索引分四类:

  • index ---- 普通索引、数据可以重复

  • fulltext ---- 全文索引,用来对大表的文本域(char,varchar,text)进行索引

  • unique ---- 唯一索引,要求所有记录都唯一

  • primary key ---- 主键索引,也就是在唯一索引的基础上相应的列必须为主键

2、使用索引需注意:

(1). 只对 where 和order by 需要查询的字段设置索引,避免无意义的硬盘开销;

(2). 组合索引支持前缀索引;

(3). 更新表的时候,如增删记录,mysql会自动更新索引,保持树的平衡;因此更多的索引意味着更多的维护成本

3、索引建立原则

(1). 尽量减少like,但不是绝对不可用,”xxxx%” 是可以用到索引的

(2). 表的主键、外键必须有索引

(3). 谁的区分度更高(同值的最少),谁建索引,区分度的公式是count(distinct(字段))/count(*)

(4). 单表数据太少,不适合建索引

(5). where,order by ,group by 等过滤时,后面的字段最好加上索引

(6). 如果既有单字段索引,又有这几个字段上的联合索引,一般可以删除联合索引

(7). 联合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替

(8). 联合索引: mysql 从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index(a,b,c). 可以支持 a|a,b|a,b,c 3种组合进行查找,但不支持 b,c 进行查找.当最左侧字段是常量引用时,索引就十分有效。

(9). 前缀索引: 有时候需要索引很长的字符列,这会让索引变得大且慢。通常可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率。其缺点是不能用于ORDER BY和GROUP BY操作,也不能用于覆盖索引 Covering index(即当索引本身包含查询所需全部数据时,不再访问数据文件本身)。

(10). NULL会导致索引形同虚设

4、禁用索引

- like “ %xxx ”

- not in , !=

- 对列进行函数运算的情况(如 where md5(password) = “xxxx”)

- WHERE index=1 OR A=10

- 存了数值的字符串类型字段(如手机号),查询时记得不要丢掉值的引号,否则无法用到该字段相关索引,反之则没关系

004、MySQL慢查询优化

  1. 开启查询缓存,优化查询

  2. explain你的select查询,这可以帮你分析你的查询语句或是表结构的性能瓶颈。EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的

  3. 当只要一行数据时使用limit 1,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据

  4. 为搜索字段建索引

  5. 使用 ENUM 而不是 VARCHAR。如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是VARCHAR

  6. Prepared StatementsPrepared Statements很像存储过程,是一种运行在后台的SQL语句集合,我们可以从使用 prepared statements 获得很多好处,无论是性能问题还是安全问题。Prepared Statements 可以检查一些你绑定好的变量,这样可以保护你的程序不会受到“SQL注入式”攻击

  7. 垂直分表

  8. 选择正确的存储引擎

005、数据库隔离级别

MySQL的四种隔离级别如下:

  • 未提交读(READ UNCOMMITTED)

这就是上面所说的例外情况了,这个隔离级别下,其他事务可以看到本事务没有提交的部分修改.因此会造成脏读的问题(读取到了其他事务未提交的部分,而之后该事务进行了回滚).

这个级别的性能没有足够大的优势,但是又有很多的问题,因此很少使用.

  • 已提交读(READ COMMITTED)

其他事务只能读取到本事务已经提交的部分.这个隔离级别有 不可重复读的问题,在同一个事务内的两次读取,拿到的结果竟然不一样,因为另外一个事务对数据进行了修改.

  • REPEATABLE READ(可重复读)

可重复读隔离级别解决了上面不可重复读的问题(看名字也知道),但是仍然有一个新问题,就是 幻读,当你读取id> 10 的数据行时,对涉及到的所有行加上了读锁,此时例外一个事务新插入了一条id=11的数据,因为是新插入的,所以不会触发上面的锁的排斥,那么进行本事务进行下一次的查询时会发现有一条id=11的数据,而上次的查询操作并没有获取到,再进行插入就会有主键冲突的问题.

  • SERIALIZABLE(可串行化)

这是最高的隔离级别,可以解决上面提到的所有问题,因为他强制将所以的操作串行执行,这会导致并发性能极速下降,因此也不是很常用.

006、数据库四大特性

1)原子性(Atomicity)

一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。


2)一致性(Consistency)

事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。


3)隔离性(Isolation)

指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据


4)持久性(Durability)

指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。

007、MySQL有哪些锁

一、按锁粒度分类:行级锁&表级锁

1 行级锁 (行级锁分为共享锁和排他锁

(1) 描述

行级锁是mysql中锁定粒度最细的一种锁。表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突,其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁和排他锁

(2)特点

开销大,加锁慢,会出现死锁。发生锁冲突的概率最低,并发度也最高。

InnoDB有三种行锁的算法:


a,Record Lock(记录锁):单个行记录上的锁。这个也是我们日常认为的行锁。


b,Gap Lock(间隙锁):间隙锁,锁定一个范围,但不包括记录本身(只不过它的锁粒度比记录锁的锁整行更大一些,他是锁住了某个范围内的多个行,包括根本不存在的数据)。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况。该锁只会在隔离级别是RR或者以上的级别内存在。间隙锁的目的是为了让其他事务无法在间隙中新增数据。


c,Next-Key Lock(临键锁):它是记录锁和间隙锁的结合,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。next-key锁是InnoDB默认的锁


2 表级锁(表共享读锁(共享锁)与表独占写锁(排他锁)

(1) 描述

表级锁是mysql中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分mysql引擎支持。最常使用的MyISAM与InnoDB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)

(2)特点

开销小,加锁快,不会出现死锁。发生锁冲突的概率最高,并发度也最低。

  • LOCK TABLE my_table_name READ;  用读锁锁表,会阻塞其他事务修改表数据。

  • LOCK TABLE my_table_name WRITE; 用写锁锁表,会阻塞其他事务读和写。


二、锁级别分类:共享锁 & 排他锁 & 意向锁


1 共享锁(Share Lock)

共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。

用法:SELECT … LOCK IN SHARE MODE;

在查询语句后面增加LOCK IN SHARE MODE,MySQL 就会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。


2 排他锁(Exclusive Lock)

排他锁又称写锁、独占锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。

用法 :SELECT … FOR UPDATE;

在查询语句后面增加FOR UPDATE,MySQL 就会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。


3 意向锁(Intention Lock)

意向锁是表级锁,其设计目的主要是为了在一个事务中揭示下一行将要被请求锁的类型。InnoDB 中的两个表锁:

    • 意向共享锁(IS):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁;

    • 意向排他锁(IX):类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。

意向锁是 InnoDB 自动加的,不需要用户干预。对于INSERT、UPDATE和DELETE,InnoDB 会自动给涉及的数据加排他锁;对于一般的SELECT语句,InnoDB 不会加任何锁,事务可以通过以下语句显式加共享锁或排他锁。

意向锁的提出仅仅为了在之后加表级别的S锁和X锁时可以快速判断表中的记录是否被上锁,以避免用遍历的方式来查看表中有没有上锁的记录。就是说当对一个行加锁之后,如果有打算给行所在的表加一个表锁,必须先看看该表的行有没有被加锁,否则就会出现冲突。IS锁和IX锁就避免了判断表中行有没有加锁时对每一行的遍历。直接查看表有没有意向锁就可以知道表中有没有行锁。


三、从加锁策略上分:乐观锁和悲观锁


悲观锁认为对于同一个数据的并发操作,一定是会发生修改的(或者增删改多,查少),哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为,不加锁的并发操作一定会出问题。


乐观锁则认为对于同一个数据的并发操作,是不会发生修改的(或者增删改少,查多)。在更新数据的时候,会采用不断尝试更新的方式来修改数据。也就是先不管资源有没有被别的线程占用,直接取申请操作,如果没有产生冲突,那就操作成功,如果产生冲突,有其他线程已经在使用了,那么就不断地轮询。乐观的认为,不加锁的并发操作是没有事情的。就是通过记录一个数据历史记录的多个版本,如果修改完之后发现有冲突再将版本返回到没修改的样子,乐观锁就是不加锁。好处就是减少上下文切换,坏处是浪费CPU时间。


四、其他:自增锁


自增锁是一种特殊的表级锁,主要用于事务中插入自增字段,也就是我们最常用的自增主键id。通过innodb_autoinc_lock_mode参数可以设置自增主键的生成策略。防止并发插入数据的时候自增id出现异常。


当一张表的某个字段是自增列时,innodb会在该索引的末位加一个排它锁。为了访问这个自增的数值,需要加一个表级锁,不过这个表级锁的持续时间只有当前sql,而不是整个事务,即当前sql执行完,该表级锁就释放了。其他session无法在这个表级锁持有时插入任何记录。

008、主键索引和聚簇索引的区别

009、MySQL死锁的原因和解决办法

多数情况下,可以认为如果一个资源被锁定,它总会在以后某个时间被释放。而死锁发生在当多个进程访问同一数据库时,其中每个进程拥有的锁都是其他进程所需的,由此造成每个进程都无法继续下去。简单的说,进程 A 等待进程 B 释放他的资源,B 又等待 A 释放他的资源,这样就互相等待就形成死锁。


虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件:


互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合 {P0,P1,P2,•••,Pn} 中的 P0 正在等待一个 P1 占用的资源;P1 正在等待 P2 占用的资源,……,Pn 正在等待已被 P0 占用的资源。

解决办法:

  • 设置获得锁的超时时间。

  • 按同一顺序访问对象

  • 避免事务中的用户交互。

  • 保持事务简短并在一个批处理中。

  • 使用低隔离级别。

  • 使用绑定连接。


010、普通索引和主键索引的区别

主键索引和非主键索引的区别是:非主键索引的叶子节点存放的是主键的值,而主键索引的叶子节点存放的是整行数据,其中非主键索引也被称为二级索引,而主键索引也被称为聚簇索引

011、MVCC的实现原理

012、数据库三大范式

第一范式

第二范式

第二范式:非主属性完全函数依赖于候选键。如PersonID,ProductID,ProductName,PersonName可以看到,PersonID和ProductID是联合主键,但是ProductName是依赖于ProductID的,只依赖了部分主键,没有依赖全部主键。需要拆分成三个表:PersonID、PersonName &&ProductID, ProductName&&PersonID, ProductID

第三范式

第三范式:每一列数据都和主键直接相关,而不能间接相关。即没有传递依赖。

如OrderID,ProductID,ProductName,OrderID是主键,但是ProductID依赖了OrderID,而ProductName依赖了ProductID,等于说是间接依赖了OrderID,所以需要拆分为两个表:OrderID, ProductID和ProductID, ProductName

这里需要指明范式不是最好的,我们需要混合使用范式和反范式

范式的优点

因为相对来说有较少的重复数据,范式化的更新操作要比反范式快。同时范式化需要更少的distinct和order by。

范式的缺点

通常需要关联,不仅代价昂贵,也可能会使的一些索引无效。

常用的反范式方法:

复制:在两个表中根据实际业务情况存储部分相同的字段列,即有利于查询,也不会把表搞的太大

缓存:对于需要多次join查询的表,可以在一个表中加入一个缓存列,用来缓存所join表的部分常用数据,如count等,我们需要实时更新该缓存

013、binlog相关

014、MySQL有哪些数据类型及区别

015、MyISAM和InnoDB的区别

  1. InnoDB支持事务,MyISAM不支持对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

  2. InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;

  3. InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此主键不应该过大,因为主键太大,其他索引也都会很大。而MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

  4. InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

  5. Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;

MySQL掌握70点

016、隔离级别和锁的关系

017、数据库乐观锁和悲观锁是什么?怎么实现

悲观锁(Pessimistic Lock), 每次去查询数据的时候都认为别人会修改,所以每次在查询数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就用到了这种锁机制,比如通过select ....for update进行数据锁定。


乐观锁(Optimistic Lock), 每次去查询数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号,时间戳等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。

018、Hash索引和B+树索引的区别

019、MySQL为什么不使用B树而是要用B+树作为索引的存储结构

1、B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

2、B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

3、B+树更便于遍历:由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

4、B+树更适合基于范围的查询:B树在提高了IO性能的同时并没有解决元素遍历的我效率低下的问题,正是为了解决这个问题,B+树应用而生。B+树只需要去遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作或者说效率太低。

020、联合索引是什么,最左前缀原则是什么


021、索引失效的情况有哪些?

022、explain 有哪些字段,分别是什么意思?

023、一条SQL的执行流程

 1、连接器。客户端和服务器 tcp 握手后,验证用户名密码。用户名密码通过后,连接器会到权限表中查询你拥有的权限。之后这个连接里面的权限判断逻辑,都将依赖于此时读到的权限。这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。

  2、查询缓存。如果缓存开启,则查询缓存,key 是查询的语句,value 是查询的结果。(如果找到结果直接返回客户端)

  3、分析器。MySQL 首先识别关键字确定你要做什么,然后会对 sql 语法分析,然后将 SQL 解析成 认识的语法,如果有问题,MySQL 会抛出语法错误。

  4、优化器。比如:在表里面有多个索引的时候,决定使用哪个索引。或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。

  5、执行器。首先判断对操作表有没有权限,如果有权限就执行调用存储引擎的 api 接口获取数据,如果没有权限就报错。


024、SQL语句的解析顺序

查询中用到的关键词主要包含六个,并且他们的顺序依次为


select--from--where--group by--having--order by


其中select和from是必须的,其他关键词是可选的,这六个关键词的执行顺序 。执行顺序与sql语句的书写顺序并不是一样的,而是按照下面的顺序来执行


from--where--group by--having--select--order by


from:需要从哪个数据表检索数据


where:过滤表中数据的条件


group by:如何将上面过滤出的数据分组


having:对上面已经分组的数据进行过滤的条件  


select:查看结果集中的哪个列,或列的计算结果


order by :按照什么样的顺序来查看返回的数据

025、为什么用自增列作为主键

1、如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引。

如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引。

如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。


2、数据记录本身被存于主索引(一颗B+Tree)的叶子节点上,这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放

因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)


3、如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页


4、如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销

同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

========================================

不过,如果涉及到大数据量的排序、全表扫描、count之类的操作的话,还是MyISAM占优势些,因为索引所占空间小,这些操作是需要在内存中完成的

026、B+树索引和哈希索引的区别

B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且同层级的节点间有指针相互链接,是有序的,如下图:

MySQL掌握70点

哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可,是无序的,如下图所示:

MySQL掌握70点


  1. hash索引进行等值查询更快(一般情况下),但是却无法进行范围查询.

  2. hash索引不支持使用索引进行排序,原理同上.

  3. hash索引不支持模糊查询以及多列索引的最左前缀匹配.原理也是因为hash函数的不可预测.AAAAAAAAB的索引没有相关性.

  4. hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询.

  5. hash索引虽然在等值查询上较快,但是不稳定.性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差.而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低.

027、哈希索引的优势

等值查询,哈希索引具有绝对优势(前提是:没有大量重复键值,如果大量重复键值时,哈希索引的效率很低,因为存在所谓的哈希碰撞问题。)

028、哈希索引不适用的场景

  1. 不支持范围查询

  2. 不支持索引完成排序

  3. 不支持联合索引的最左前缀匹配规则

029、B树和B+树的区别

一共做了两个地方的改进:

a. 把数据项从非叶子节点移到了叶子节点—>目的:腾出更多空间存放索引(非叶子节点存放的索引数目越多,则该树能存放的数据就越多),减少层数,即减少磁盘I/O操作的次数,以提高性能。(在树高度相等的情况下,B+树存储的数据比B树要大得多)

b. 加了一个区间访问的双向指针 ,利用该指针可以得到左右两边节点,提高区间访问的性能。这也是为什么不用hash索引的原因。当进行单值查找的时候,用hash索引比较高效,但是一到范围索引就不行

030、为什么说B+比B树更适合实际应用中操作系统的文件索引和数据库索引?

在B+树中为什么要把data数据项移动到叶子节点中:每个节点最多放置16K大小的数据,这样能给每个节点腾出来更多的空间存放索引,也可减少层数,提高性能。

031、表分区与分表的区别

032、行级锁定的优点和缺点

优点:

  1. 当在许多线程中访问不同的行时只存在少量锁定冲突。

  2. 回滚时只有少量的更改

  3. 可以长时间锁定单一的行。

缺点:

  1. 比页级或表级锁定占用更多的内存。

  2. 当在表的大部分中使用时,比页级或表级锁定速度慢,因为你必须获取更多的锁。

  3. 如果你在大部分数据上经常进行GROUP BY操作或者必须经常扫描整个表,比其它锁定明显慢很多。

  4. 用高级别锁定,通过支持不同的类型锁定,你也可以很容易地调节应用程序,因为其锁成本小于行级锁定。

033、数据库表创建注意事项

1、字段名及字段配制合理性

  • 剔除关系不密切的字段;

  • 字段命名要有规则及相对应的含义(不要一部分英文,一部分拼音,还有类似a.b.c这样不明含义的字段);

  • 字段命名尽量不要使用缩写(大多数缩写都不能明确字段含义);

  • 字段不要大小写混用(想要具有可读性,多个英文单词可使用下划线形式连接);

  • 字段名不要使用保留字或者关键字;

  • 保持字段名和类型的一致性;

  • 慎重选择数字类型;

  • 给文本字段留足余量;

2、系统特殊字段处理及建成后建议

  • 添加删除标记(例如操作人、删除时间);

  • 建立版本机制;

3、表结构合理性配置

  • 多型字段的处理,就是表中是否存在字段能够分解成更小独立的几部分(例如:人可以分为男人和女人);

  • 多值字段的处理,可以将表分为三张表,这样使得检索和排序更加有调理,且保证数据的完整性!

4、其它建议

  • 对于大数据字段,独立表进行存储,以便影响性能(例如:简介字段);

  • 使用varchar类型代替char,因为varchar会动态分配长度,char指定长度是固定的;

  • 给表创建主键,对于没有主键的表,在查询和索引定义上有一定的影响;

  • 避免表字段运行为null,建议设置默认值(例如:int类型设置默认值为0)在索引查询上,效率立显;

  • 建立索引,最好建立在唯一和非空的字段上,建立太多的索引对后期插入、更新都存在一定的影响(考虑实际情况来创建);

034、ACID靠什么保证的呢

  1. A原子性由undo log日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql

  2. C一致性一般由代码层面来保证

  3. I隔离性由MVCC来保证

  4. D持久性由内存+redo log来保证,mysql修改数据同时在内存和redo log记录这次操作,事务提交的时候通过redo log刷盘,宕机的时候可以从redo log恢复

035、什么是间隙锁

间隙锁是可重复读级别下才会有的锁,结合MVCC和间隙锁可以解决幻读的问题。我们还是以user举例,假设现在user表有几条记录


e data-draft-node=“block” data-draft-type=“table” data-size=“normal” data-row-style=“normal”>

当我们执行:


begin; select * from user where age=20 for update; begin; insert into user(age) values(10); #成功 insert into user(age) values(11); #失败 insert into user(age) values(20); #失败 insert into user(age) values(21); #失败 insert into user(age) values(30); #失败


只有10可以插入成功,那么因为表的间隙mysql自动帮我们生成了区间(左开右闭)


(negative infinity,10],(10,20],(20,30],(30,positive infinity)


由于20存在记录,所以(10,20],(20,30]区间都被锁定了无法插入、删除。


如果查询21呢?就会根据21定位到(20,30)的区间(都是开区间)。


需要注意的是唯一索引是不会有间隙索引的。


036、mysql主从同步怎么做的

  1. master提交完事务后,写入binlog

  2. slave连接到master,获取binlog

  3. master创建dump线程,推送binglog到slave

  4. slave启动一个IO线程读取同步过来的master的binlog,记录到relay log中继日志中

  5. slave再开启一个sql线程读取relay log事件并在slave执行,完成同步

  6. slave记录自己的binglog

MySQL掌握70点

由于mysql默认的复制方式是异步的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。由此产生两个概念。

全同步复制:主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,但是很显然这个方式的话性能会受到严重影响。

半同步复制:和全同步不同的是,半同步复制的逻辑是这样,从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成。

037、JDBC连接数据库(编辑)步骤

1、注册驱动:Class.forName("com.mysql.jdbc.Driver");显示的加载到JVM中

2、获取连接:Connection conn=DriverManager.getConnection(url,user,pass);

     DriverManager下的方法:getConnection(String url,String username,String password)

3、创建一个Statement语句对象:

    Statement stmt=conn.createStatement();

               PreparedStatement pstmt = conn.PreparedStatement() ;

4、执行SQL语句: ResultSet rs=stmt.executeQuery(Sql); 除了查询语句是executeQuery();其他全部是executeUpdate();

5.处理结果集:ResultSet对象的getXxxx方法,取决于数据库中表的字段的类型

6、关闭资源:操作完以后要关闭jdbc来释放jdbc资源。先开后关


038、分区和分表的区别

分表就是按照一定的规则把一张大表给分成多张小表,在数据库中看到的是几张不同的表,在硬盘上也是不同的文件,因此在进行增删改查操作的时候要根据同样的规则去找到具体操作的表。


分区是按照一定的规则把一张大表分成不同的区块,在数据库中看到的还是一张表,只不过在硬盘上存储的时候分成了几个不同的文件。这样在进行增删改查操作的时候就像操作一张普通的表一样简单方便。

 

他们都是为了处理单张表的大数据量问题,都能提高性能。

039、什么是覆盖索引和回表

覆盖索引指的是在一次查询中,如果一个索引包含或者说覆盖所有需要查询的字段的值,我们就称之为覆盖索引,而不再需要回表查询。

而要确定一个查询是否是覆盖索引,我们只需要explain sql语句看Extra的结果是否是“Using index”即可。


040、xx



041、CHAR和VARCHAR的区别

长度大小区别:

  • CHAR(M)定义的列的长度为固定的,M取值可以为0~255之间;

  • VARCHAR(M)定义的列的长度为可变长,M取值可以为0~65535之间,(VARCHAR的最大有效长度由最大行大小和使用 的字符集确定。整体最大长度是65,532字节)。

存数据时的区别:

  • CHAR值存储时,如果字符数没有达到定义的位数,会在后面用空格补全,再存入数据库中。比如定义 CHAR(10),那么不论存储的数据是否达到了10个字节,都要占去10个字节的空间,不足的自动用空格填充;

  • VARCHAR值保存时只保存需要的字符数,另加一个字节来记录长度(如果列声明的长度超过255,则使用两个字节)。VARCHAR值保存时不进行填充。

取数据时的区别:

  • 数据库取CHAR值时,尾部的空格会被删除;

  • 数据库取VARCHAR值时,尾部的空格仍然保留。


042、delete、drop、truncate区别

  • truncate 和 delete只删除数据,不删除表结构 ,drop删除表结构,并且释放所占的空间。

  • 删除数据的速度,drop> truncate > delete

  • delete属于DML语言,需要事务管理,commit之后才能生效。drop和truncate属于DDL语言,操作立刻生效,不可回滚。

使用场合:

  • 当你不再需要该表时, 用 drop;

  • 当你仍要保留该表,但要删除所有记录时, 用 truncate;

  • 当你要删除部分记录时(always with a where clause), 用 delete.

注意:对于有主外键关系的表,不能使用truncate而应该使用不带where子句的delete语句,由于truncate不记录在日志中,不能够激活触发器

========================================================

drop直接删掉表 truncate删除表中数据,再插入时自增长id又从1开始 delete删除表中数据,可以加where字句。

(1) DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。TRUNCATE TABLE 则一次性地从表中删除所有的数据并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。

(2) 表和索引所占空间。当表被TRUNCATE 后,这个表和索引所占用的空间会恢复到初始大小,而DELETE操作不会减少表或索引所占用的空间。drop语句将表所占用的空间全释放掉。

(3) 一般而言,drop > truncate > delete

(4) 应用范围。TRUNCATE 只能对TABLE;DELETE可以是table和view

(5) TRUNCATE 和DELETE只删除数据,而DROP则删除整个表(结构和数据)。

(6) truncate与不带where的delete :只删除数据,而不删除表的结构(定义)drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger)索引(index);依赖于该表的存储过程/函数将被保留,但其状态会变为:invalid。

(7) delete语句为DML(data maintain Language),这个操作会被放到 rollback segment中,事务提交后才生效。如果有相应的 tigger,执行的时候将被触发。

(8) truncate、drop是DLL(data define language),操作立即生效,原数据不放到 rollback segment中,不能回滚

(9) 在没有备份情况下,谨慎使用 drop 与 truncate。要删除部分数据行采用delete且注意结合where来约束影响范围。回滚段要足够大。要删除表用drop;若想保留表而将表中数据删除,如果于事务无关,用truncate即可实现。如果和事务有关,或老师想触发trigger,还是用delete。

(10) Truncate table 表名 速度快,而且效率高,因为:truncate table 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。

(11) TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。

(12) 对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。

043、索引类型

1、普通索引:最基本的索引,没有任何约束。


2、唯一索引:与普通索引类似,但具有唯一性约束。


3、主键索引:特殊的唯一索引,不允许有空值。


4、复合索引:将多个列组合在一起创建索引,可以覆盖多个列。


5、外键索引:只有InnoDB类型的表才可以使用外键索引,保证数据的一致性、完整性和实现级联操作。


6、全文索引:MySQL 自带的全文索引只能用于 InnoDB、MyISAM ,并且只能对英文进行全文检索,一般使用全文索引引擎。


  所有存储引擎对每个表至少支持16个索引,总索引长度至少为256字节,索引有两种存储类型,包括B型树索引和哈希索引。索引可以提高查询的速度,但是创建和维护索引需要耗费时间,同时也会影响插入的速度,如果需要插入大量的数据时,最好是先删除索引,插入数据后再建立索引。

043、解释MySQL外连接、内连接与自连接的区别

先说什么是交叉连接: 交叉连接又叫笛卡尔积,它是指不使用任何条件,直接将一个表的所有记录和另一个表中的所有记录一一匹配。


内连接 则是只有条件的交叉连接,根据某个条件筛选出符合条件的记录,不符合条件的记录不会出现在结果集中,即内连接只连接匹配的行。外连接 其结果集中不仅包含符合连接条件的行,而且还会包括左表、右表或两个表中的所有数据行,这三种情况依次称之为左外连接,右外连接,和全外连接。


左外连接,也称左连接,左表为主表,左表中的所有记录都会出现在结果集中,对于那些在右表中并没有匹配的记录,仍然要显示,右边对应的那些字段值以NULL来填充。右外连接,也称右连接,右表为主表,右表中的所有记录都会出现在结果集中。左连接和右连接可以互换,MySQL目前还不支持全外连接。


044、什么是聚簇索引和非聚簇索引


  • 聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据

  • 非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因

澄清一个概念:innodb中,在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找,非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引,辅助索引叶子节点存储的不再是行的物理位置,而是主键值


045、非聚簇索引一定会回表查询吗

不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询.

举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行

select age from employee where age < 20

的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询.


046、同时有多个事务在进行会怎么样呢?

多事务的并发进行一般会造成以下几个问题:

  • 脏读: A事务读取到了B事务未提交的内容,而B事务后面进行了回滚.

  • 不可重复读: 当设置A事务只能读取B事务已经提交的部分,会造成在A事务内的两次查询,结果竟然不一样,因为在此期间B事务进行了提交操作.

  • 幻读: A事务读取了一个范围的内容,而同时B事务在此期间插入了一条数据.造成"幻觉".


047、MySQL的binlog有有几种录入格式?分别有什么区别?

有三种格式,statement,row和mixed.

  • statement模式下,记录单元为语句.即每一个sql造成的影响会记录.由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制.

  • row级别下,记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大.

  • mixed. 一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row.

此外,新版的MySQL中对row级别也做了一些优化,当表结构发生变化的时候,会记录语句而不是逐行记录.


048、超大分页怎么处理?

MySQL掌握70点

049、关心过业务系统里面的sql耗时吗?统计过慢查询吗?对慢查询都怎么优化过?

在业务系统中,除了使用主键进行的查询,其他的我都会在测试库上测试其耗时,慢查询的统计主要由运维在做,会定期将业务中的慢查询反馈给我们.

慢查询的优化首先要搞明白慢的原因是什么? 是查询条件没有命中索引?是load了不需要的数据列?还是数据量太大?

所以优化也是针对这三个方向来的,

  • 首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写.

  • 分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引.

  • 如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表.

050、数据库优化的思路



051、MySQL 有必要开启查询缓存吗?

1、查询缓存需要每次将查询查询结果以查询语句(key)和查询结果(value)的方式存储起来,这些都是一些资源消耗。

  2、对于操作频繁的表没有必要开启缓存,因为简单的更新操作就会使缓存失效,这样会导致有些缓存还未使用就已经失效了。

  3、如果是一张静态表,很长时间才会更新一次,可以开启缓存,这样缓存的命中率会高一些。

  4、需要注意的是 MySQL 8.0 已经把查询缓存功能放弃了。

052、查询优化器工作流程

一条 sql 有很多条查询方案,在一条 sql 真正执行之前,查询优化器会找出 sql 所有执行的方案进行分析,然后对比找出成本最低的方案,但是成本最低的方案并不是响应时间最短的方案。

    优化过程大致如下:

  1、根据搜索条件,找出所有可能使用的索引。

  2、计算全表扫描的代价。

  3、计算使用不同索引执行查询的代价。

  4、对比各种执行方案的代价,找出成本最低的那一个。

053、索引的优点

  1、大大减少了服务器需要扫描的数据行数。

  2、帮助服务器避免进行排序和分组。

  3、以及避免创建临时表(b+tree 索引是有序的,可以用于 order by 和 group by 操作。临时表主要是在排序和分组过程中创建,不需要排序和分组,也就不需要创建临时表)。

  4、将随机 i/o 变为顺序 i/o(b+tree 索引是有序的,会将相邻的数据都存储在一起)。

  5、是最有效的查询优化手段。

054、什么是索引下推?

MySQL 5.6引入了索引下推优化。默认开启,使用SET optimizer_switch = ‘index_condition_pushdown=off;可以将其关闭。

主要目的:减少IO

索引下推优点:

A. 减少存储引擎查询基础表的次数。

B. 可以减少MySQL服务器从存储引擎接收数据的次数。

C. 在InnoDB中只针对二级索引有效 ,因为InnDB的聚簇索引会将整行数据读到InnDB的缓冲区,这样一来索引条件下推的主要目的减少IO次数就失去了意义。因为数据已经在内存中了,不再需要去读取了。

解释:

譬如,在 people_table中有一个二级索引(zipcode,lastname,firstname),查询是SELECT * FROM people WHERE zipcode=’95054′ AND lastname LIKE ‘%etrunia%’ AND address LIKE ‘%Main Street%’;

--------没有使用索引条件下推技术:MySQL会通过zipcode=’95054’从存储引擎中查询对应的数据,返回到MySQL服务端,然后MySQL服务端基于lastname LIKE ‘%etrunia%’ and address LIKE ‘%Main Street%’来判断数据是否符合条件 。

---------使用了索引下推技术:MYSQL首先会返回符合zipcode=’95054’的索引,然后根据lastname LIKE ‘%etrunia%’ and address LIKE ‘%Main Street%’来判断索引是否符合条件。如果符合条件,则根据该索引来定位对应的数据,如果不符合,则直接reject掉 。(只有当索引符合条件时才会将数据检索出来返回给MySQL服务器。)


055、请说说 InnoDB 的 4 大特性

  • 插入缓冲(insert buffer)

  • 二次写(double write)

  • 自适应哈希索引(ahi)

  • 预读(read ahead)

056、MySQL 索引的“创建”原则

1、最适合索引的列是出现在 WHERE 子句中的列,或连接子句中的列,而不是出现在 SELECT 关键字后的列。


2、索引列的基数越大,索引效果越好。


3、根据情况创建复合索引,复合索引可以提高查询效率。因为复合索引的基数会更大。


4、避免创建过多的索引,索引会额外占用磁盘空间,降低写操作效率。


5、主键尽可能选择较短的数据类型,可以有效减少索引的磁盘占用提高查询效率。


6、对字符串进行索引,应该定制一个前缀长度,可以节省大量的索引空间。


057、MySQL 索引的“使用”注意事项?

1、应尽量避免在 WHERE 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描。优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。注意,column IS NULL 也是不可以使用索引的。


2、应尽量避免在 WHERE 子句中使用 OR 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:SELECT id FROM t WHERE num = 10 OR num = 20 。


3、应尽量避免在 WHERE 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。


4、应尽量避免在 WHERE 子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。


5、不要在 WHERE 子句中的 = 左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。


6、复合索引遵循前缀原则。


7、如果 MySQL 评估使用索引比全表扫描更慢,会放弃使用索引。如果此时想要索引,可以在语句中添加强制索引。


8、列类型是字符串类型,查询时一定要给值加引号,否则索引失效。


9、LIKE 查询,% 不能在前,因为无法使用索引。如果需要模糊匹配,可以使用全文索引。


058、聚簇索引的注意点有哪些?

聚簇索引表最大限度地提高了 I/O 密集型应用的性能,但它也有以下几个限制:


1、插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于 InnoDB 表,我们一般都会定义一个自增的 ID 列为主键。关于这一点,可能面试官会换一个问法。例如,为什么主键需要是自增 ID ,又或者为什么主键需要带有时间性关联。


2、更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB 表,我们一般定义主键为不可更新。MySQL 默认情况下,主键是允许更新的。对于 MongoDB ,其 主键是不允许更新的。


3、二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。当然,有一种情况可以无需二次查找,基于非主键索引查询,但是查询字段只有主键 ID ,那么在二级索引中就可以查找到。


4、主键 ID 建议使用整型。因为,每个主键索引的 B+Tree 节点的键值可以存储更多主键 ID ,每个非主键索引的 B+Tree 节点的数据可以存储更多主键 ID 。


059、大表优化

  1. 限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。;

  2. 读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读;

  3. 缓存: 使用MySQL的缓存,另外对重量级、更新少的数据可以考虑使用应用级别的缓存;

  4. 垂直分区:根据数据库里面数据表的相关性进行拆分。 例如,用户表中既有用户的登录信息又有用户的基本信息,可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。

  5. 水平分区:保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。水平拆分可以支撑非常大的数据量。


060、一张表,里面有ID自增主键,当insert了17条记录之后,删除了第15,16,17条记录,再把Mysql重启,再insert一条记录,这条记录的ID是18还是15 ?

MySQL掌握70点


061、解释下为什么要用自增列做主键

062、为什么推荐使用整型自增主键而不是uuid


063、Mysql优化


1、开启查询缓存,优化查询

2、explain你的select查询,这可以帮你分析你的查询语句或是表结构的性能瓶颈。EXPLAIN的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序

3、当只要一行数据时使用limit 1,Mysql数据库引擎会在找到一条数据后停止搜索,而不是继续往后查找下一条符合记录的数据

4、为搜索字段建索引

5、使用ENUM而不是VARCHAR,如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用ENUM而不是VARCHAR

6、Prepared Statement Prepared Statements很像存储过程,是一种运行在后台的sql语句集合,我们可以从使用prepared statement获得很多好处,无论是性能问题还是安全问题。Prepared Statements可以检查一些你绑定好的变量,这样可以保护你的程序不会受到“SQL注入式”攻击

7、垂直分表

8、选择正确的存储引擎

20、key和index的区别

1、key是数据库的物理结构,它包含两层意义和作用,一是约束(偏重于约束和规范数据库的结构完整性),二是索引(辅助查询用的)。包括primary key,unique key,foregin key等

2、index是数据库的物理结构,它只是辅助查询的,它创建时会在另外的表空间(mysql中的innodb表空间)以一个类似目录的结构存储。索引要分类的话,分为前缀索引、全文本索引等


064、行级锁定的优点和缺点

优点:

1、当在许多线程中访问不同的行时只存在少量锁定冲突

2、回滚时只有少量的更改

3、可以长时间锁定单一的行

缺点:

1、比页级或表级锁定占用更多的内存

2、当在表的大部分中使用时,比页级或表级锁定速度慢,因为你必须获取更多的锁

3、如果你在大部分数据上经常进行GROUP BY操作或者必须经常扫描整个表,比其它锁定明显慢很多

4、用高级别锁定,通过支持不同的类型锁定,你也可以很容易地调节应用程序,因为其锁成本小于行级锁定

065、什么情况适合建索引?什么时候不适合建索引?

MySQL掌握70点

066、索引失效情况

1、不在索引列上做任何操作(计算、函数、(自动 or 手动)类型转换),会导致索引失效而转向全表扫描

2、mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描

3、is not null 也无法使用索引,但是is null是可以使用索引的。

4、like以通配符开头(’%abc…’)mysql索引失效会变成全表扫描的操作

5、字符串不加单引号索引失效

6、


067、MySQL有哪几种索引类型,各自特点

常见的MySQL索引结构有B-树索引,B+树索引,Hash索引和全文索引


B-Tree索引

(1) 因为存储引擎不用进行全表扫描来获取数据,直接从索引的根节点开始搜索,从而能加快访问数据的速度

(2) B-Tree对索引是顺序组织存储的,很适合查找范围数据。

(3) 适用于全键值、键值范围或者键前缀查找(根据最左前缀查找)。

(4) 限制:对于联合索引来说,如果不是从最左列开始查找,则无法使用索引;不能跳过索引中的列 。


B+Tree索引

(1) 是B-Tree索引的变种,现在主流的存储引擎都不用单纯的B-Tree,而是其变种B+Tree或者T-Tree等等

(2) 和B-Tree最主要的区别就是B+Tree的内节点不存储data,只存储key,叶子节点不存储指针。


Hash索引

(1) 基于Hash表实现,只有Memory存储引擎显式支持哈希索引 。

(2) 适合等值查询,如=、in()、<=>,不支持范围查询。

(3) 因为不是按照索引值顺序存储的,就不能像B+Tree索引一样利用索引完成排序 。

(4) Hash索引在查询等值时非常快

(5) 因为Hash索引始终索引的所有列的全部内容,所以不支持部分索引列的匹配查找 。

(6) 如果有大量重复键值得情况下,哈希索引的效率会很低,因为存在哈希碰撞问题。

(7) 程序员可以在B+Tree索引的基础上创建自适应Hash索引 。


全文索引

(1) MyISAM和InnoDB都支持全文索引

(2) 有三种模式:自然语言模式,布尔模式和查询扩展模式


R-Tree索引

MyISAM支持R-Tree索引,这个和全文索引基本不问

068、redo log和binlog的区别

  1. redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用

  2. redo log是物理日志,记录的是“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ” 。比如,redo log记录的是结果,binlog记录的是一个逻辑过程、

  3. redo log是循环写的,空间固定会用完;binlog是可以追加写入的。“追加写”是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志

  4. binlog可以作为恢复数据使用,主从复制搭建,redo log作为异常宕机或者介质故障后的数据恢复使用

MySQL掌握70点

MySQL掌握70点

MySQL掌握70点

MySQL掌握70点

MySQL掌握70点



069、聚簇索引的优势

看上去聚簇索引的效率明显要低于非聚簇索引,因为每次使用辅助索引检索都要经过两次B+树查找,这不是多此一举吗?聚簇索引的优势在哪?

  1. 由于行数据和叶子节点存储在一起,同一页中会有多条行数据,访问同一数据页不同行记录时,已经把页加载到了Buffer中,再次访问的时候,会在内存中完成访问,不必访问磁盘。这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来组织数据,获得数据更快

  2. 聚簇索引适合用在排序的场合,非聚簇索引不适合

  3. 取出一定范围数据的时候,使用用聚簇索引

  4. 二级索引需要两次索引查找,而不是一次才能取到数据,因为存储引擎第一次需要通过二级索引找到索引的叶子节点,从而找到数据的主键,然后在聚簇索引中用主键再次查找索引,再找到数据

  5. 可以把相关数据保存在一起。例如实现电子邮箱时,可以根据用户 ID 来聚集数据,这样只需要从磁盘读取少数的数据页就能获取某个用户的全部邮件。如果没有使用聚簇索引,则每封邮件都可能导致一次磁盘 I/O。

070、聚簇索引的劣势

  1. 维护索引很昂贵,特别是插入新行或者主键被更新导至要分页(page split)的时候。建议在大量插入新行后,选在负载较低的时间段,通过OPTIMIZE TABLE优化表,因为必须被移动的行数据可能造成碎片。使用独享表空间可以弱化碎片

  2. 表因为使用UUId(随机ID)作为主键,使数据存储稀疏,这就会出现聚簇索引有可能有比全表扫面更慢,所以建议使用int的auto_increment作为主键

  3. 主键的值是顺序的,所以 InnoDB 把每一条记录都存储在上一条记录的后面。当达到页的最大填充因子时(InnoDB 默认的最大填充因子是页大小的 15/16,留出部分空间用于以后修改),下一条记录就会写入新的页中。一旦数据按照这种顺序的方式加载,主键页就会近似于被顺序的记录填满(二级索引页可能是不一样的)

  4. 如果主键比较大的话,那辅助索引将会变的更大,因为辅助索引的叶子存储的是主键值;过长的主键值,会导致非叶子节点占用占用更多的物理空间


以上是关于MySQL掌握70点的主要内容,如果未能解决你的问题,请参考以下文章

关于在各浏览器中插入音频文件的html代码片段

20165229实验二 《Java面向对象程序设计》实验报告

android小知识点代码片段

如何分别在 70 张图像的不同位置分配按钮?

70 张图带你彻底掌握红黑树!

部分代码片段