Mysql整理


索引相

abcd合索引索ba会走索引

会,重排

 

索引的底层实现是B+何不采用红黑树,B?

(1):B+Tree非叶子储键值信息,降低B+Tree的高度,所有叶子点之都有一个,数记录都存放在叶子点中

(2):红黑树这种结构,h明要深的多,率明比B-Tree差

(3):B+也存在劣,由于会重,因此会占用更多的空。但是与来的性能优势相比,空往往可以接受,因此B+的在数中的使用比B更加广

 

索引失条件

(1):条件是or,如果or条件生or个字段加个索引

(2):like开头%

(3):如果列型是字符串,那一定要在条件中将数使用引号引用起来,否不会使用索引

(4):where中索引列使用了数或有

 

B+点?

充分利用空局部性原理,合磁的高度低,能在存大量数情况下,少的磁IO。能好支持单值范围查询,有序性查询

索引和数更多的索引存在内存中。

非叶子能存索引,叶子点才存。叶子点是照大小排序的,比便于查找范围查询更好。

所有的索都会在叶子点中终结

 

索引的分

 

结构角度

B+索引

 

Hash索引[拉法解决冲突]

希算法时间复杂O(1)

希索引支持等较查询 不支持范围查询

 Hash索引法被用来避免数的排序操作

 Hash索引不能利用部分索引键查询

 Hash索引在任何候都不能避免表

 Hash索引遇到大量Hash相等的情况后性能并不一定就会比BTree索引高

 

Full-Text全文索引

full-text在mysql里有myisam支持,而且支持full-text的字段有char、varchar、text数型。full-text主要是用来代替like "%***%"率低下的问题

 

R-Tree索引

r-tree在mysql少使用,支持geometry数型,支持该类型的存有myisam、bdb、innodb、ndb、archive几。相于b-tree,r-tree的优势在于范围查找.

 

物理存角度

 

集索引(clustered index)

行的物理序与列(一般是主的那一列)的逻辑顺序相同,一个表中有一个集索引

行的物理序与列序相同,如果我们查询id比较靠后的数,那么这行数的地在磁中的物理地也会比较靠后。而且由于物理排列方式与集索引的序相同,所以也就能建立一个集索引了。

简单 innodb 的索引和数是在一起的 ,myism的索引和数是分

 

集索引(non-clustered index)

助索引(secondary index)集索引和非集索引都是B+树结构

 

逻辑角度

 

索引

索引是一特殊的唯一索引,不有空

 

普通索引或者单列索引

每个索引包含单个列,一个表可以有多个单列索引

 

多列索引(复合索引、联合索引)

复合索引指多个字段上创建的索引,有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用复合索引时遵循最左前缀集合唯一索引或者非唯一索引

 

空间索引

空间索引是对空间数类型的字段建立的索引,MYSQL中的空间数类型有4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON。 MYSQL使用SPATIAL关键字进行扩展,使得能够用于创建正规索引类型的语法创建空间索引。创建空间索引的列,必须将其声明为NOT NULL,空间索引能在存储引擎为MYISAM的表中创建为什么MySQL 索引中用B+tree,不用B-tree 或者其他树,为什么不用 Hash 索引

 

 

B与B+的区

B+树查询时间复杂度固定是logn,B树查询复杂度最好是 O(1)。

B+接点的指可以大大加区间访问性,可使用在范围查询等,而B-树每点 key 和 data 在一起,法区间查找

B+合外部存,也就是磁。由于内 data 域,点能索引的范围更大更精

注意个区相当重要,是基于(1)(2)(3)的,B树每点即保存数又保存索引,所以磁IO的次数少,B+有叶子点保存,磁IO多,但是区间访问好。

 

不用B索引的数结构

B+与B相比,有以下优势:更少的IO次数:B+的非叶包含,而不包含真,因此点存记录个数比B数多多(即m更大),因此B+的高度更低,访问时所需要的IO次数更少。此外,由于点存记录数更多,所以对访问局部性原理的利用更好,存命中率更高。更范围查询:在B范围查询时,首先到要查找的下限,然后B树进行中序遍,直到查找的上限;而B+范围查询需要对链行遍即可。更定的查询率:B查询时间复杂度在1到高之(分别对应记录在根点和叶点),而B+查询复杂则稳为树高,因所有数都在叶点。

 

用B+数索引的数结构

高度相固定,有控制io次数。

所有叶子点形成了一个有序表,更加便于范围查找

B+合外部存,由于内data域,一个点可以存更多的内点,点能索引的范围更大更精,也意味着B+树单次磁IO的信息量大于B,IO率更高。

 

MySQL数要用B+索引?而不用红黑树、Hash、B

红黑树:如果在内存中,红黑树查找率比B更高,但是及到磁操作,B就更了。因为红黑树是二,数量大时树高,的根点向下寻找程,每读1个点,都相当于一次IO操作,因此红黑树的I/O操作会比B多的多。

hash 索引:如果查询单,hash 索引的率非常高。但是 hash 索引有几个问题:1)不支持范围查询;2)不支持索引的排序操作;3)不支持合索引的最左匹配规则

B索引:B索相比于B+,在范围查询时,需要局部的中序遍,可能要跨层访问,跨层访问代表着要外的磁I/O操作;外,B的非叶子点存放了数记录的地,会致存放的点更少,高。

 

是回表查询

InnoDB 中,于主索引,需要走一遍主索引的查询就能在叶子到数

于普通索引,叶子点存的是 key + 主键值,因此需要再走一次主索引,通索引到行记录就是所的回表查询,先定位主键值,再定位行记录

 

走普通索引,一定会出回表查询吗

不一定,如果查询语句所要求的字段全部命中了索引,那就不必再行回表查询

容易理解,有一个 user 表,主键为 id,name 普通索引,行:select id, name from user where name = 'joonwhee' ,通name 的索引就能到 id 和 name了,因此需再回表去行了。

一个1了?

Innodb中,B+中的一个点存的内容是:

非叶子点:key + 指

叶子点:数行(key 通常是数的主

于叶子点:我1行数大小1k(于普通业务绝对够了),那1能存16条数

于非叶子点:key 使用 bigint 则为8字,指在 MySQL 中6字,一共是14字16k能存放 16 * 1024 / 14 = 1170个。那高度3的B+能存的数:1170 * 1170 * 16 = 21902400(千万)。

所以在 InnoDB 中B+高度一般3层时,就能足千万的数。在查找一次查找代表一次IO,所以通索引查询通常需要1-3次 IO 操作即可查找到数。千万级别对于一般的业务了,所以一个1,也就是16k是比合理的。

 

与索引相互作用的程?

如果一个主被定则该密集索引

若没有定则该表的第一个或唯一非空作密集索引

若不足以上条件,innodb内部会生成一个

 

索引与非索引的区

都是B+的数结构

  • 索引:

与索引放到了一起,并且是照一定的组织的,到索引就到了数,数的物理存放数与索引的序是一致的 即:要索引是相的,那么对应的数也一定是相的。

索引中的个叶子点包含主键值、事ID、回(rollback pointer用于事和MVCC)和余下的列

  • 索引:

叶子点不存,存的是数行地,也就是索引到数行的位置,再去磁盘查找似于的目,根录找到了数,再去查找数。

MYISAM是与行号来组织索引的。的叶子点中保存的实际上是指向存放数的物理的指

MYISAM存的物理文件我能看出,MYISAM引的索引文件(.MYI)和数文件(.MYD)是相互独立的。

 

(1):Myiasm是mysql的存,不支持数,行级锁,外入更新需表,率低,查询速度快,Myisam使用的是非集索引

(2):innodb 支持事,底层为B+树实现理多重并更新操作,普通select都是快照,快照不加。InnoDb使用的是集索引

 

Mysql有日志?

  • Binlog

记录所有的更改。 查询日志 记录了来自客端的所有句 慢查询日志 记录了所有响应时间过阈值的SQL句,阈值可以自己置,参数long_query_time,其认值为10s,且关闭的状,需要手的打

  •  Error Log 

 错误日志文件,错误日志文件记录了MySQL启动行,关闭记录,同包含一警告信息,当发现MySQL有常的候,应该第一时间查错误日志文件。 SHOW VARIABLES LIKE 'log_error' 

  •  Slow Log 

查询日志可以行超指定时间的SQL,记录到日志中,情况下MySQL并不启动查询日志,用需要手工将个参数ON

 

SHOW VARIABLES LIKE 'log_slow_queries'; //查询是否开启查询日志

 

ShOW VARIABLES LIKE 'long_query_time'; //查询慢日志的阈值10s

 

SHOW VARIABLES LIKE 'log_queries_not_using_indexes'; //记录所有没有使用索引的SQL

 

SHOW VARIABLES LIKE 'log_throttle_queries_not_using_indexes'; //置没有记录索引的SQL的行次数阈值有超过这阈值记录

 

SHOW VARIABLES LIKE 'log_output'; //看出日志出格式

  • 查询日志 

查询日志记录了所有MySQL数的所有求信息,论这求是否得到了正行。 

  • Binary Log 

制日志记录了MySQL数库执行的所有的更改操作,但是不包括SELECT和SHOW等操作。通制日志,可以到以下几功能: :通制日志制:在主候,通制日志,将主数信息同审计:通制日志,可以统计操作,看是否存在SQL注入

 

InnoDB日志

  • 1 Redo Log 重日志,用于记录操作的化,且记录的是修改之后的。不管事是否提交都会记录下来。例如在更新数,会先将更新的记录写到Redo Log中,再更新存中中的数。然后置的更新策略,将内存中的数刷回磁
  • 2 Undo Log 记录的是记录的事务开始之前的一个版本,可用于事之后生的回。 Redo Log记录的是具体某个数上的修改,能在当前Server使用,而Binlog可以理解可以其他型的存使用。也是Binlog的一个重要作用,那就是主制,外一个作用是数据恢

 

,是InnoDB中数管理的最小位。当我们查询,其是以页为单位,将磁中的数冲池中的。同理,更新数也是以页为单位,将我们对的修改刷回磁每页大小16k,每页中包含了若干行的数

自己的存的数对应的行格式存在User Records中。实际上,新生成的面是没有User Records的,有当我第一次入数,才会Free Space一个记录大小的空间给User Records。当Free Space用完之后,就意味着当前的数也使用完了。

的数,可以通FileHeader中的上一下和下一的数可以形成双向表。因实际的物理存上,数并不是连续的。可以把他理解成G1的Region在内存中的分布。

而一中所包含的行数,行与行之间则形成了表。我存入的行数会到User Records中,当然最初User Records并不占任何存着我存入的数越来越多,User Records会越来越大,Free Space的空会越来越小,直到被占用完,就会申新的数

User Records中的数,是照主id来行排序的,当我照主查找时,会沿着表一直往后

 

文件有

MyISAM 物理文件结构为

.frm文件:与表相的元数信息都存放在frm文件,包括表结构的定信息等

.MYD (MYData) 文件:MyISAM 存擎专用,用于存MyISAM 表的数

.MYI (MYIndex)文件:MyISAM 存擎专用,用于存MyISAM 表的索引相信息

InnoDB 物理文件结构为

.frm 文件:与表相的元数信息都存放在frm文件,包括表结构的定信息等

.ibd 文件或 .ibdata 文件: 这两种文件都是存放 InnoDB 数的文件,之所以有两种文件形式存放 InnoDB 的数,是因 InnoDB 的数方式能配置来决定是使用共享表空存放存是用独享表空存放存

独享表空方式使用.ibd文件,并且个表一个.ibd文件

共享表空方式使用.ibdata文件,所有表共同使用一个.ibdata文件(或多个,可自己配置)

 

 

务说是如何实现的?

(1):通过预写日志方式实现的,redo和undo机制是数库实现的基

(2):redo日志用来在断/数等状况重演一次刷数程,把redo日志里的数刷到数里,保了事的持久性(Durability)

(3):undo日志是在事务执行失销对的操作,保了事的原子性

 

Mysql是否解决了幻,是如何解决的?

Mysql的离级别是Repeatable read(可重复读),这种离级别下会生幻读问题,Mysql通过锁机制及多版本控制解决了幻读现象的生,主要手段如下:

快照务每次取数候都会取建版本小于当前事版本的数,以及期版本大于当前版本的快照数。普通的 select 就是快照。当行select操作是innodb行快照,会记录次select后的果,之后select 的候就会返回次快照的数,即使其他事提交了不会影当前select的数实现了可重复读了。

当前在 InnoDB 中,认为 Repeatable 级别,InnoDB 中使用一被称 next-key locking 的策略来避免幻(phantom)象的生。主要采用next-key,即行和gap来控制。如select * from user where id =1 for update;如果有id1的记录则会被加排(X),如果不存在,会加上next-key,此时插记录是会排出常的,以此解决幻读问题

 

事物的隔离级别

READ-UNCOMMITTED(未提交): 最低的隔离级别许读未提交的数更,可能会脏读、幻或不可重复读

READ-COMMITTED(已提交): 许读取并提交的数,可以阻止脏读,但是幻或不可重复读有可能生。

REPEATABLE-READ(可重复读): 同一字段的多次果都是一致的,除非数是被本身事自己所修改,可以阻止脏读和不可重复读,但幻有可能生。

SERIALIZABLE(可串行化): 最高的隔离级别,完全服ACID的隔离级别。所有的事依次逐个行,这样就完全不可能生干,也就是该级别可以防止脏读、不可重复读以及幻

 

快照与当前的区

1. 快照

MVCC 的 SELECT 操作是快照中的数,不需要行加操作。

SELECT * FROM table ...;

2. 当前

MVCC 其库进行修改的操作(INSERT、UPDATE、DELETE)需要行加操作,取最新的数。可以看到 MVCC 并不是完全不用加,而是避免了 SELECT 的加操作。

INSERT;

UPDATE;

DELETE;

 

多版本控制如何实现的?

undo log

undo log有个作用:提供回和多个行版本控制(MVCC)。undo log主要存的也是逻辑日志,比如我要insert一条数了,那undo log会记录的一条对应的delete日志。我要update一条记录时记录一条对应相反的update记录

insert undo log – 记录insert

update undo log – 记录update和delete,undo 是逻辑记录记录一行修改的(前后)。

  • 实现原理

而MVVC引入了外一控制,让读写操作互不阻一个写操作都会建一个新版本的数操作会有限多个版本的数中挑一个最合果直接返回,由此解决了事争条件。

多版本控制的核心是数快照,而 InnoDB 是通 undo log 来存快照。InnoDB 通 undo log 保存了已更改行的旧版本的信息的快照。

InnoDB 的内部实现为每一行数加了三个列用于实现 MVCC 。DB_ROW_ID: 行标识单调id)DB_TRX_ID: 入或更新行的最后一个事的事务标识符。(视为更新,将其标记为除)DB_ROLL_PTR:写入回段的消日志记录(若行已更新,消日志记录包含在更新行之前重建行内容所需的信息)根事物标识符及销记录决定取的快照版本。

 

事物的程?

1 记录redo和undo log文件,保日志在磁上的

2 更新数库记录

3 提交事 redo写入 commit记录

 

制的原理

(1):主db的更新事件(update、insert、delete)被写到binlog

(2):主库创建一个binlog dump thread线程,把binlog的内容送到

(3):库创建一个I/O线程,取主库传过来的binlog内容并写入到relay log.

(4):库还建一个SQL线程,relay log里面取内容写入到slave的db.

 

 

Explain字段语义

 

[?重点:]

type

const>eq_ref>ref>fulltext>ref_or_null>index_merge >unique_subquery>index_subquery>range>index>all" width="361" height="41">

Index all 需要

Extra

 

 

信息比的字段

 

id

SELECT 查询标识符. 个 SELECT 都会自分配一个唯一的标识符.

 

Table

查询的是个表

 

partitions

匹配的分区

 

possible_keys

表示 MySQL 在查询时,可能使用到的索引。即使有索引出在 possible_key 中,但是并不表示此索引一定会被 MySQL 使用到。MySQL 在查询时具体使用到那索引,与 key 和写的 SQL 有

 

key_len

表示查询优化器使用了索引的字数。个字段可以合索引是否完全被使用,或有最左部分字段被使用到。

 

ref

个字段或常数与 key 一起被使用

 

Filtered

表示此查询条件所过滤的数的百分比

 

重要的字段信息

 

select_type

 

SIMPLE: 表示此查询不包含 UNION 查询或子查询

 

PRIMARY: 表示此查询是最外查询

 

UNION: 表示此查询是 UNION 的第二或后的查询

 

DEPENDENT UNION: UNION 中的第二个或后面的查询语句, 取决于外面的查询

 

UNION RESULT: UNION 的

 

SUBQUERY: 子查询中的第一个 SELECT

 

DEPENDENT SUBQUERY: 子查询中的第一个 SELECT, 取决于外面的查询. 即子查询于外层查询果 最常应该是 SIMPLE,当我查询 SQL 里面没有 UNION 查询或者子查询候,那通常就是 SIMPLE 型。

 

Type

type 字段比重要,提供了判断查询是否高的重要依 type 字段,我可以判断此次查询是全表描,是索引描等。 通常来, 不同的 type 型的性能系如下: ALL < index < range ~ index_merge < ref < eq_ref < const < system ALL 型因是全表描,因此在相同的查询条件下,是速度最慢的。 而 index 型的查询虽然不是全表描,但是描了所有的索引,因此比 ALL 型的快。 后面的几种类型都是利用了索引来查询,因此可以过滤部分或大部分数,因此查询率就比高了。

 

system 表中有一条数型是特殊的 const 型。

 

const 针对或唯一索引的等值查询扫描,最多返回一行数,const 查询速度非常快,因仅仅读取一次即可。

eq_ref 此型通常出在多表的 join 查询,表示于前表的一个果,都能匹配到后表的一行果,并且查询的比操作通常是 =,查询高.

 

range 表示使用索引范围查询,通索引字段范围获取表中部分数记录型通常出在 =、 <>、 >、 >=、 <、 <=、 IS NULL、 <=>、 BETWEEN、 IN 操作中。 当 type 是 range ,那 EXPLAIN 出的 ref 字段 NULL, 并且 key_len 字段是此次查询中使用到的索引的最的那个。

 

index 表示全索引描(full index scan),和 ALL 似, ALL 型是全表描,而 index 则仅仅扫描所有的索引,而不描数。 index 型通常出在:所要查询的数直接在索引中就可以取到,而不需要描数。当是这种情况,Extra 字段 会示 Using index。

 

ALL 表示全表描,型的查询是性能最差的查询之一。通常来,我查询应该 ALL 型的查询,因为这样查询在数量大的情况下,的性能是巨大的灾难。 如一个查询是 ALL 查询,那一般来可以的字段添加索引来避免。

 

 

key

此次查询切使用到的索引.

 

 

rows

rows 也是一个重要的字段。MySQL 查询优化器根统计信息,算 SQL 要查找果集需要取的数行数。非常直观显示 SQL 的率好坏,原上 rows 越少越好。

 

 

Extra

 

个也比重要

 

Using filesort 当 Extra 中有 Using filesort ,表示 MySQL 需外的排序操作,不能通索引到排序果。一般有 Using filesort,都建议优化去,因为这样查询 CPU 源消耗大。

 

Using index 覆索引描,表示查询在索引中就可查找所需数,不用描表数文件,往往明性能不.

 

Using temporary 查询有使用临时表,一般出于排序,分和多表 join 的情况,查询率不高,建议优化。

 

Using where 列数仅仅使用了索引中的信息而没有实际的行的表返回的,这发生在表的全部的求列都是同一个索引的部分的候,表示 MySQL 服器将在存擎检索行后再过滤

 

 

使用B+树呢

b+的高度固定,可以有的控制io次数,并且在一个中可以存更多的索引

 

是mvcc?

MVCC 是操作的一种实现方式,MVCC 主要又是依 Read View 来实现的.MySQL 会根规则来判断版本中的个版本(记录)是在事中可的.DB_TRX_ID:列表示此记录的事 IDDB_ROLL_PTR:列表示一个指向回段的指实际就是指向该记录的一个版本DB_ROW_ID:记录的 ID,如果有指定主,那么该值就是主。如果没有主,那就会使用定的第一个唯一索引。如果没有唯一索引,那就会生成一个。READ COMMITTED 是在行 select 操作都会生成一次 Read View。REPEATABLE READ 有在第一次行 select 操作才会生成 Read View,后的 select 操作都将使用第一次生成的 Read View。

 

会不会走索引的问题

abc建立索引相当于a,ab,abc建立索引,如果查询bc示走索引,但是type是index,相当于全索引描,如果查询确顺typeref,是正匹配的索引。如果行cba等查询序不同,会自重排走索引。

 

建立索引原

尽量选择区分度高的字段,首先考where和orderby的字段上

 

不会走索引的情况?

1 Like的参数以通配符开头时,like ‘%test%’,不使用索引,like ‘test%’,使用索引

2 where条件不符合最左前则时

3 使用!= 或 <> 操作符

4 索引列参与算,where句中有数学算或者数。

5 字段行null判断,如select * from t_credit_detail where Flistid is null ;

6 or操作符必须每个字段都建立索引

 

使用自

由于主使用了索引,如果主是自id,那么对应的数也会相地存放在磁上,写入性能高。如果是uuid等字符串形式,繁的入会使innodb繁地移盘块,写入性能就比低了。[就是用自的好]

 

mysql如何解决幻读问题

Mysql的离级别是Repeatable read(可重复读),这种离级别下会生幻读问题,Mysql通过锁机制及多版本控制解决了幻读现象的生,主要手段如下:

快照务每次取数候都会取建版本小于当前事版本的数,以及期版本大于当前版本的快照数。普通的 select 就是快照。当行select操作是innodb行快照,会记录次select后的果,之后select 的候就会返回次快照的数,即使其他事提交了不会影当前select的数实现了可重复读了。

当前在 InnoDB 中,认为 Repeatable 级别,InnoDB 中使用一被称 next-key locking 的策略来避免幻(phantom)象的生。主要采用next-key,即行和gap来控制。如select * from user where id =1 for update;如果有id1的记录则会被加排(X),如果不存在,会加上next-key,此时插记录是会排出常的,以此解决幻读问题

 

B+的特性?

1.所有关键字都出在叶子点的表中(密索引),且表中的关键好是有序的;

2.不可能在非叶子点命中;

3.非叶子点相当于是叶子点的索引(疏索引),叶子点相当于是存关键字)数的数

4.更合文件索引系

 

用B+数索引的数结构

IO是一消耗性能的操作。

B+高度相固定,有控制io次数。

所有叶子点形成了一个有序表,更加便于范围查找

B+合外部存,由于内data域,一个点可以存更多的内点,点能索引的范围更大更精,也意味着B+树单次磁IO的信息量大于B,IO率更高。

 

char 和 varchar的区

char是固定度,varchar度可.char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字个数,比如 CHAR(30) 就可以存 30 个字符。存储时,前者不管实际度,直接 char 定的度分配存;而后者会根实际的数分配最的存.

 

int(11)最大度是多少?

个11代表度,与整数需要的存的大小都没有系,最大值还是21亿

 

是快照是当前

1. 快照

MVCC 的 SELECT 操作是快照中的数,不需要行加操作。SELECT * FROM table ...;

 

2. 当前

MVCC 其库进行修改的操作(INSERT、UPDATE、DELETE)需要行加操作,取最新的数。可以看到 MVCC 并不是完全不用加,而是避免了 SELECT 的加操作。INSERT;UPDATE;DELETE;

行 SELECT 操作,可以制指定行加操作。以下第一个句需要加 S ,第二个需要加 X 。SELECT * FROM table WHERE ? lock in share mode;SELECT * FROM table WHERE ? for update;

 

置慢查询

如果不改配置文件,重启会失效

 

对主键索引或唯一索引会用gap锁么

如果where条件全部命中,不会用gap锁只会加纪录锁

如果where条件部分命中或者全不命中,会加gap