mysql面试题

事务的基本要素(ACID)

1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位

2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

事务的并发问题

1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致

3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

MySQL事务隔离级别

事务隔离级别脏读不可重复读幻读
读未提交(read-uncommitted) 是 是 是 不可重复读(read-committed) 否 是 是 可重复读(repeatable-read) 否 否 是 串行化(serializable) 否 否 否

mysql默认的事务隔离级别为repeatable-read
你可以在my.inf文件的[mysqld]节里类似如下设置该选项:
transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}

1、读未提交:客户端A,客户端B,客户端B更一条数据,虽然客户端B的事务还没提交,但是客户端A就可以查询到B已经更新的数据,一旦客户端B的事务因为某种原因回滚,所有的操作都将会被撤销,那客户端A查询到的数据其实就是脏数据

2,读已提交
客户端A执行查询,客户端B修改了数据,客户端A执行与上一步相同的查询,结果 与上一步不一致,即产生了不可重复读的问题
3,可重复读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
4.串行化: mysql中事务隔离级别为serializable时会锁表,因此不会出现幻读的情况,这种隔离级别并发性极低,开发中很少会用到。

说一下 mysql 常用的引擎?

InnoDB 引擎:MySQL 的5.5之后的默认引擎,InnoDB 引擎提供了对数据库事务的支持,并且还提供了行级锁和外键的约束,它的设计的目标就是处理大数据容量的数据库系统。MySQL 运行的时候,InnoDB 会在内存中建立缓冲池,用于缓冲数据和索引。由于锁的粒度小,写操作是不会锁定全表的,所以在并发度较高的场景下使用会提升效率的。

MyISAM 引擎:不提供事务的支持,也不支持行级锁和外键。因此当执行插入和更新语句时,即执行写操作的时候需要锁定这个表,所以会导致效率会降低。不过和 InnoDB 不同的是,MyIASM 引擎是保存了表的行数,于是当进行 select count(*) from table 语句时,可以直接的读取已经保存的值而不需要进行扫描全表。所以,如果表的读操作远远多于写操作时,并且不需要事务的支持的,可以将 MyIASM 作为数据库引擎的首选。

MyISAM与InnoDB区别

InnoDB聚簇索引,MyISAM非聚簇索引
InnoDB数据与索引一起保存.ibd,MyISAM表结构.frm 索引.myi 数据.myd
InnoDB支持事务、外键、行锁表锁,MyISAM不支持事务、外键、只支持表锁
select count(*)
MyISAM查询更优,InnoDB更新更优
都是B+tree索引
MyISAM支持全文索引,InnoDB5.6后支持

MyISAM:

不支持事务,但是每次查询都是原子的
支持表级锁,每次操作对整个表加锁
存储表的总行数
一个MyISAM表有三个文件:表结构.frm 索引.myi 数据 .myd
采用非聚集索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性。

Innodb:

支持ACID事务,支持四种隔离级别
支持行级锁及外键约束,因此支持写并发
不存储总行
主键索引采用聚集索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值;因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使用自增主键,防止插入数据时,为维持B+树结构,文件的大调整

聚簇索引和非聚簇索引的区别

聚簇索引: 将数据存储与索引放到了一块,找到索引也就找到了数据。
非聚簇索引: 将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因。
主键索引和普通索引的区别: 主键索引只要搜索ID这个B+Tree即可拿到数据。普通索引先搜索索引拿到主键值,再到主键索引树搜索一次(回表)。
聚簇索引具有唯一性,由于聚簇索引是将数据跟索引结构放到一块,因此一个表仅有一个聚簇索引。

char和varchar的区别

1.CHAR的长度是不可变的,而VARCHAR的长度是可变的,也就是说,定义一个CHAR[10]和VARCHAR[10],如果存进去的是‘ABCD’, 那么CHAR所占的长度依然为10,除了字符‘ABCD’外,后面跟六个空格,而VARCHAR的长度变为4了,取数据的时候CHAR类型的要用trim()去掉多余的空格,而VARCHAR类型是不需要的。

2、CHAR的存取速度要比VARCHAR快得多,因为其长度固定,方便程序的存储与查找;但是CHAR为此付出的是空间的代价,因为其长度固定,所以难免会有多余的空格占位符占据空间,可以说是以空间换取时间效率,而VARCHAR则是以空间效率为首位的。

3、CHAR的存储方式是,一个英文字符(ASCII)占用1个字节,一个汉字占用两个字节;而VARCHAR的存储方式是,一个英文字符占用2个字节,一个汉字也占用2个字节。

mysql中的int(11)到底代表什么意思

这里的int(11)不是表示限制int的长度为11,而是字符的显示宽度,在字段类型为int时,无论你显示宽度设置为多少,int类型能存储的最大值和最小值永远都是固定的

那么这个显示宽度到底有什么用呢?

当 int 字段类型设置为无符号且填充零(UNSIGNED ZEROFILL)时,当数值位数未达到设置的显示宽度时,会在数值前面补充零直到满足设定的显示宽度,为什么会有无符号的限制呢,是因为 ZEROFILL 属性会隐式地将数值转为无符号型,因此不能存储负的数值
CREATE TABLE int_demo (
id INT(11) NOT NULL AUTO_INCREMENT,
a INT(11) NOT NULL,
b INT(11) UNSIGNED ZEROFILL NOT NULL,
c INT(5) DEFAULT NULL,
d INT(5) UNSIGNED ZEROFILL NOT NULL,
e INT(15) DEFAULT NULL,
PRIMARY KEY (id)
)

INSERT INTO int_demo (a, b, c, d, e) VALUES (1, 1, 1, 1, 1);
INSERT INTO int_demo (a, b, c, d, e) VALUES (1234567890, 1234567890, 1234567890, 1234567890, 1234567890);

结论:

1、如果一个字段设置了无符号和填充零属性,那么无论这个字段存储什么数值,数值的长度都会与设置的显示宽度一致,如上述例子中的字段 b,插入数值 1 显示为00000000001,左边补了 10 个零直至长度达到 11 位;

2、设置字段的显示宽度并不限制字段存储值的范围,比如字段 d 设置为 int(5),但是仍然可以存储 1234567890 这个 10 位数字;

3、设置的字符宽度只对数值长度不满足宽度时有效,如 d 字段 int(5),插入 1 时,长度不足 5,因此在左边补充 4 个零直到 5 位,但是插入 1234567890 时超过了 5 位,这时的显示宽度就起不了作用了

Innodb为什么推荐使用自增ID

①主键页就会近乎于顺序的记录填满,提升了页面的最大填充率,不会有页的浪费。

②新插入的行一定会在原有的最大数据行下一行,mysql定位和寻址很快,不会为计算新行的位置而做出额外的消耗。

③减少了页分裂和碎片的产生。

UUID:大量的随机IO+页分裂导致移动大量的数据+数据会有碎片。

总结:自增ID有序,会按顺序往最后插入,而UUID无序,随机生成,随机插入,会造成频繁页分裂,内存碎片化,大量随机IO。

索引类型

索引可以提高查询速度,查询使用优化隐藏器提高性能,但是也会占据物理空间,降低增删改的速度,因为还要操作索引文件。
1.普通索引:可以重复

2.唯一索引:唯一,可为空,表中只有一个主键索引,可多个唯一索引

3.主键索引:唯一,不为空,叶子结点存出了行记录数据,主键索引也称聚簇索引,对应非主键索引的叶子结点存的主键的值(二级索引),用二级索引查需要回表操作(根据二级索引查到主键,再根据主键去主键索引查)一般推荐用自增主键,保证空间利用率,减少页分裂

4.全文索引

5.覆盖索引:索引字段覆盖了查询语句涉及的字段,直接通过索引文件就可以返回查询所需的数据,不必通过回表操作。

6.回表:通过索引找到主键,再根据主键id去主键索引查。

7.索引下推:在根据索引查询过程中就根据查询条件过滤掉一些记录,减少最后的回表操作。
假如执行select * from stu where name=? and age=? 没有索引下推先再存储引擎根据name筛选数据返回给server层,然后server层再根据age过滤。有索引下推直接根据name和age在存储引擎层就筛选得到结果。

B树与B+树区别?为何用B+树

B+树:非叶子结点不存data,只存key,查询更稳定,增大了广度(B+树出度更大,树高矮,节点小,磁盘IO次数少);叶子结点下一级指针(范围查询);索引冗余。B树非叶子节点也可以存数据,B+树所有数据都是存储在叶子节点上的,非叶子节点不存放数据。叶子节点之间有双向链表相连适合范围查询。

与红黑树相比:
更少查询次数:B+树出度更大,树高更低,查询次数更少
磁盘预读原理:为了减少IO操作,往往不严格按需读取,而是预读。B+树叶子结点存储相临,读取会快一些。

存储更多索引结点:B+树只在叶子结点储存数据,非叶子结点存索引,而一个结点就是磁盘一个内存页,内存页大小固定,那么相比B树这些可以·存更多的索引结点,出度更大,树高矮,查询次数少,磁盘IO少。

B+树的叶子节点都可以存哪些东西?

可能存储的是整行数据,也有可能是主键的值

索引设计原则(查询快,占用空间少)

1.出现在where子句或则连接子句中的列

2.基数小的表没必要

3.使用短索引,如果索引长字符串列,应该指定前缀长度

4.定义有外键的数据列一定索引

5.不要过度索引

6.更新频繁的不适合

7.区分度不高的不适合,如性别

8.尽量扩展索引,别新建索引,如(a)->(a,b)

9.字符串字段建立索引方法
1、直接创建完整索引,这样可能比较占用空间;
2、创建前缀索引,节省空间,但会增加查询扫描次数,并且不能使用覆盖索引;
3、倒序存储,再创建前缀索引,用于绕过字符串本身前缀的区分度不够的问题;
4、额外用一个字段进行索引,额外计算开销
总结:索引设计原则要求查询快,占用空间少;一般建在where条件,匹配度高的;要求基数大,区分度高,不要过大索引,尽量扩展,用联合索引,更新频繁不适合、使用短索引。

索引失效场景

1.以“%”开头的like语句,索引无效,后缀“%”不影响

2.or语句前后没有同时使用索引

3.列类型是字符串,一定要在条件中将数据用引号引用,否则失效(隐式转换)

4.如果mysql估计使用全表扫描比索引快,则不用索引(键值少,重复数据多)

5.组合索引要遵守最左前缀原则——不使用第一列索引 失效

6.在索引字段上使用not,<>,!= (对它处理是全表扫描)

7.对索引字段进行计算操作,字段使用函数也会失效

8.is null

如何创建索引?

ALTER TABLE table_name ADD INDEX index_name (column_list);

CREATE INDEX index_name ON table_name (column_list);

在create table时创建

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

查询字段全部命中索引,覆盖索引,不走回表,直接从索引得到结果,不要查数据文件
总结:覆盖索引就不走回表

联合索引的建立规则

将查询需求频繁或者字段选择性高的列放在前面
索引的复用,可以少维护一些索引(a)->(a,b)
如果既有联合查询,又有基于a、b各自的查询呢?考虑的原则就是空间,将小的单独建索引

最左匹配原则

从左往右匹配,直到遇到范围查询。建立联合索引(a,b,c)索引是先根据a排序,a相同时b有序,a不同无序,以此类推。总之遇到范围查询就停。

(a,b)联合索引 [(2,4),(),()]
|/ |/
[(1,1),(1,2),(2,1)] [(2,4),(3,1),(3,2)]
规律:a有顺序(1,1,2,2,2,3,3)b无顺序,a相同时b又有顺序,不同a之间b没有顺序,所以a=1,b>2走联合索引;a>1,b>2不走索引。

select * from table_name where a = ‘1’ and b = ‘2’ and c = ‘3’
//全值匹配查询,用到索引,与顺序无关,查询优化器,会自动优化查询顺序

select * from table_name where a = ‘1’
select * from table_name where a = ‘1’ and b = ‘2’
select * from table_name where a = ‘1’ and b = ‘2’ and c = ‘3’
//匹配左边的列时,用到了索引

select * from table_name where b = ‘2’
select * from table_name where c = ‘3’
select * from table_name where b = ‘1’ and c = ‘3’
//没有用到索引

select * from table_name where a = ‘1’ and c = ‘3’
//a用到了索引,b、c没有到

select * from table_name where a > 1 and a < 3 and b > 1;
//只有a用到索引,在1<a<3的范围内b是无序的,不能用索引,找到1<a<3的记录后,只能根据条件 b > 1继续逐条过滤

select * from table_name where a = 1 and b > 3;
// a=1的情况下b是有序的,进行范围查找走的是联合索引 走 a b索引(a相同时b有序)

一条sql执行很慢的原因?

一个 SQL 执行的很慢,我们要分两种情况讨论:
1、大多数情况下很正常,偶尔很慢,则有如下原因
(1)、数据库在刷新脏页,例如 redo log 写满了需要同步到磁盘。
(2)、执行的时候,遇到锁,如表锁、行锁。
(3)、sql写的烂了
2、这条 SQL 语句一直执行的很慢,则有如下原因
(1)、没有用上索引或则索引失效:例如该字段没有索引;由于对字段进行运算、函数操作导致无法用索引。
(2)、有索引可能会走全表扫描
怎样判断是否走全表扫描:
索引区分度(索引的值不同越多,区分度越高),称为基数,而数据量大时不可能全部扫描一遍得到基数,而是采样部分数据进行预测,那有可能预测错了,导致走全表扫描。

SQL优化

1、应尽量避免全表扫描,应考虑在where及order by涉及的列上建立索引。
2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询select id from t where num=0。
3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20可以这样查询:select id from t where num=10 union all select id from t where num=20
5.in 和 not in 也要慎用,否则会导致全表扫描
6.对于连续的数值,能用 between 就不要用 in 了
7.查询也将导致全表扫描 select id from t where name like ‘%abc%’
8.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
9.尽量避免大事务操作,提高系统并发能力。

COUNT()

1、COUNT有几种用法?
count() count(列名) count(1)三种用法。阿里巴巴java开发手册中提及到:强制不要使用count(列名) count(1)来代替count()
count(*)是sql92定义的用来统计行数的语法,跟null与非null无关。

2、COUNT(字段名)和COUNT()的查询结果有什么不同?
count(字段名)如果该字段为null 那么他不统计null忽略null值 count()将null值也统计进来,包含null值的行数
count(字段)进行统计的时候会将整个字段进行非空判断,效率比count(*)低

3、COUNT(1)和COUNT()之间有什么不同?
COUNT(常量) 和 COUNT()表示的是直接查询符合条件的数据库表的行数。而COUNT(列名)表示的是查询符合条件的列的值
不为NULL的行数。

4、COUNT(1)和COUNT()之间的效率哪个更高?
对于COUNT(1)和COUNT(),MySQL的优化是完全一样的,根本不存在谁比谁快!

5、为什么《阿里巴巴Java开发手册》建议使用COUNT()
建议使用COUNT()!因为这个是SQL92定义的标准统计行数的语法

MySQL的MyISAM引擎对COUNT()做了哪些优化?

MyISAM做了一个简单的优化,那就是它可以把表的总行数单独记录下来,如果从一张表中使用COUNT()进行查询的时候
可以直接返回这个记录下来的数值就可以了,当然,前提是不能有where条件。

什么是mysql事务?事务的四大特性是什么?

事务是恢复和并发控制的基本单位。是一组原子性的sql查询,或者说是一个独立的工作单元。事务内的语句要么全部执行成功要么全部失败。
事务的四大特性:
原子性(Atomicity)
一致性(Consistency)
隔离性(Isolation)
持久性(Durability)
原子性(通过undolog日志来实现的):
一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么
全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性

一致性(一致性是事务的最终追求,一致性是通过其他三个特性来实现的):
数据库总是从一个一致性的状态转换到另一个一致性的状态。(在前面的例子中,一致性确保了,即
使在转账过程中系统崩溃,支票账户中也不会损失200美元,因为事务最终没有提交,所以事务中所做
的修改也不会保存到数据库中。)

隔离性(通过mvcc+锁来实现的):
通常来说,一个事务所做的修改操作在提交事务之前,对于其他事务来说是不可见的。(在前面的例
子中,当执行完第三条语句、第四条语句还未开始时,此时有另外的一个账户汇总程序开始运行,则
其看到支票帐户的余额并没有被减去200美元。)

持久性(通过redo log日志来实现的):
一旦事务提交,则其所做的修改会永久保存到数据库。
说明:事务能够保证数据的完整性和一致性,让用户的操作更加安全。

查询语句执行流程

1.先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在
MySQL8.0 版本以前,会先查询缓存,以这条 sql 语句为 key 在内存中查询是否有结
果,如果有直接缓存,如果没有,执行下一步。

2.通过分析器进行词法分析,提取 sql 语句的关键元素,比如提取上面这个语句是查
询 select,提取需要查询的表名,需要查询所有的列,查询条件。然后判断这个 sql 语句是否有语法错误,比如关键词是否正确等等,
如果检查没问题就执行下一步。

3.接下来就是优化器进行确定执行方案

那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,
有时候不一定最好)。那么确认了执行计划后就准备开始执行了。

4.进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎
接口,返回引擎的执行结果

更新语句执行流程

来给张三修改下年龄
1.先查询到张三这一条数据,如果有缓存,也是会用到缓存。

2.然后拿到查询的语句,把 age 改为 19,然后调用引擎 API 接口,写入这一行数据,
InnoDB 引擎把数据保存在内存中,同时记录 redo log,此时 redo log 进入 prepare
状态,然后告诉执行器,执行完成了,随时可以提交。

3.执行器收到通知后记录 binlog,然后调用引擎接口,提交 redo log 为提交状态。
4.更新完成。

这里肯定有同学会问,为什么要用两个日志模块,用一个日志模块不行吗?
这是因为最开始 MySQL 并没有 InnoDB 引擎(InnoDB 引擎是其他公司以插件形式插入
MySQL 的),MySQL 自带的引擎是 MyISAM,但是我们知道 redo log 是 InnoDB 引擎
特有的,其他存储引擎都没有,这就导致会没有 crash-safe 的能力(crash-safe 的能力即
使数据库发生异常重启,之前提交的记录都不会丢失),binlog 日志只能用来归档。
并不是说只用一个日志模块不可以,只是 InnoDB 引擎就是通过 redo log 来支持事务
的。那么,又会有同学问,我用两个日志模块,但是不要这么复杂行不行,为什么 redo
log 要引入 prepare 预提交状态?这里我们用反证法来说明下为什么要这么做?
先写 redo log 直接提交,然后写 binlog,假设写完 redo log 后,机器挂了,
binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但
是这个时候 bingog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一
条数据,同时主从同步也会丢失这一条数据。
先写 binlog,然后写 redo log,假设写完了 binlog,机器异常重启了,由于没有
redo log,本机是无法恢复这一条记录的,但是 binlog 又有记录,那么和上面同样
的道理,就会产生数据不一致的情况。
如果采用 redo log 两阶段提交的方式就不一样了,写完 binglog 后,然后再提交 redo
log 就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个
极端的情况呢?假设 redo log 处于预提交状态,binglog 也已经写完了,这个时候发生
了异常重启会怎么样呢? 这个就要依赖于 MySQL 的处理机制了,MySQL 的处理过程如
下:
判断 redo log 是否完整,如果判断是完整的,就立即提交。
如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完
整,如果完整就提交 redo log, 不完整就回滚事务。
这样就解决了数据一致性的问题。

总结

MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存、分析
器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行
引擎都可以共用,redolog 只有 InnoDB 有。
引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory 等。
查询语句的执行流程如下:权限校验(如果命中缓存)—>查询缓存—>分析器—>
优化器—>权限校验—>执行器—>引擎
更新语句执行流程如下:分析器---->权限校验---->执行器—>引擎—redo
log(prepare 状态)—>binlog—>redo log(commit状态)

mysql语句的书写顺序和执行顺序有很大差异。

书写顺序,mysql的一般书写顺写为:

select

<要返回的数据列>

from

<表名>

join

on

where

group by

<分组条件>

having

<分组后的筛选条件>

order by

<排序条件>

limit

<行数限制>

然而其执行顺序却是:

from

<表名> # 笛卡尔积

on

<筛选条件> #对笛卡尔积的虚表进行筛选

join

#指定join,用于添加数据到on之后的虚表中,例如left join会将左表的剩余数据添加到虚表中

where

#对上述虚表进行筛选

group by

<分组条件> #分组

#用于having子句进行判断,在书写上这类聚合函数是写在having判断里面的

having

<分组筛选> #对分组后的结果进行聚合筛选

select

<返回数据列表> #返回的单列必须在group by子句中,聚合函数除外

distinct

order by

<排序条件> #排序

limit

<行数限制>

部分解释:

  1. from:select * from table_1, table_2; 与 select * from table_1 join table_2; 的结果一致,都是表示求笛卡尔积;

用于直接计算两个表笛卡尔积,得到虚拟表VT1,这是所有select语句最先执行的操作,其他操作时在这个表上进行的,也就是from操作所完成的内容

  1. on: 从VT1表中筛选符合条件的数据,形成VT2表;

  2. join: 将该join类型的数据补充到VT2表中,例如left join会将左表的剩余数据添加到虚表VT2中,形成VT3表;若表的数量大于2,则会重复1-3步;

  3. where: 执行筛选,(不能使用聚合函数)得到VT4表;

  4. group by: 对VT4表进行分组,得到VT5表;其后处理的语句,如select,having,所用到的列必须包含在group by条件中,没有出现的需要用聚合函数;

  5. having: 筛选分组后的数据,得到VT6表;

  6. select: 返回列得到VT7表;

  7. distinct: 用于去重得到VT8表;

  8. order by: 用于排序得到VT9表;

  9. limit: 返回需要的行数,得到VT10;

注意:

group by条件中,每个列必须是有效列,不能是聚合函数;

null值也会作为一个分组返回;

除了聚合函数,select子句中的列必须在group by条件中;

binlog和redolog有什么区别?

redolog是在InnoDB存储引擎层产生,而binlog是MySQL数据库的上层服务层产生的。
两种日志记录的内容形式不同。MySQL的binlog是逻辑日志,其记录是对应的SQL语句。而innodb存储引擎层面的重做日志是物理日志。
两种日志与记录写入磁盘的时间点不同,binlog日志只在事务提交完成后进行一次写入。而innodb存储引擎的重做日志在事务进行中不断地被写入,并日志不是随事务提交的顺序进行写入的。
binlog不是循环使用,在写满或者重启之后,会生成新的binlog文件,redolog是循环使用。
binlog可以作为恢复数据使用,主从复制搭建,redolog作为异常宕机或者介质故障后的数据恢复使用。

如果一张表数据量级是千万级别以上的,那么,给这张表添加索引,你需要怎么做呢?

解析: 我们需要知道一点,给表添加索引的时候,是会对表加锁的。如果不谨慎操作,有可能出现生产事故的。可以参考以下方法:

1.先创建一张跟原表A数据结构相同的新表B。
2.在新表B添加需要加上的新索引。
3.把原表A数据导到新表B
4.rename新表B为原表的表名A,原表A换别的表名;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值