1. 如何创建和删除数据库?
创建数据库CREATEDATABASE数据库名;删除数据库drop database 数据库名;
2. MyISAM与InnoDB的区别?
InnoDB 支持事务;MyISAM 不支持事务
InnoDB 支持行级锁;MyISAM 支持表级锁
InnoDB 支持 MVCC(多版本并发控制);MyISAM 不支持
InnoDB 支持外键,MyISAM 不支持
InnoDB 不保存表的总行数,执行 select count(*) from table 时需要全表扫描;MyISAM 用一个变量保存表的总行数,查总行数速度很快
InnoDB 是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。辅助索引需要两次查询,先查询到主键,再通过主键查询到数据。主键太大,其他索引也会很大;MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针,主键索引和辅助索引是独立的
MyISAM 不支持事务、也不支持外键,优势是访问的速度快。对事务的完整性没有要求、以 SELECT 和 INSERT 为主的应用可以使用这个存储引擎
2.MVCC
多版本并发控制。锁机制可以控制并发操作,但是其系统开销较大,而MVCC可以在大多数情况下代替行级锁,使用MVCC,能降低其系统开销。一种乐观锁的实现。
在Mysql的InnoDB引擎中就是指在已提交读(READ COMMITTD)和可重复读(REPEATABLE READ)这两种隔离级别下的事务对于。
版本链
每一行数据都有两个隐藏的列create version和delete version
插入数据时,记录的版本号即为当前事务的版本号。
更新操作时,把旧纪录的delete veriosn改为当前版本号,然后插入一条新的记录
删除操作的时候把事务版本号作为删除版本号。
查询的时候要符合两个条件
1)删除版本号未指定或者大于当前事务版本号,即查询事务开启后确保读取的行未被删除。(即上述事务id为2的事务查询时,依然能读取到事务id为3所删除的数据行)
2) 创建版本号 小于或者等于 当前事务版本号 ,就是说记录创建是在当前事务中(等于的情况)或者在当前事务启动之前的其他事物进行的insert。
3. char与varchar的区别
char 是一种固定长度的字符串类型。varchar 是一种可变长度的字符串类型
4.建表语句中varchar(50)中50的指是什么?
字段最多存放 50 个字符,如 varchar(50) 和 varchar(200) 存储 "ConstXiong" 字符串所占空间是一样的,后者在排序时会消耗更多内存
5. int(10)中10指什么?
INT[(M)] [UNSIGNED] [ZEROFILL] M 默认为11
10 就是上述语句里的 M,指最大显示宽度,最大值为 255
最大显示宽度意思是,如果是 int(10),字段存的值是 10,则,显示会自动在之前补 8 个 0,显示为 0000000010
int 类型在数据库里面存储占 4 个字节的长度
有符号的整型范围是 -2147483648 ~ 2147483647
无符号的整型范围是 0 ~ 4294967295 2的32次方-1
6. MySQL如何获取当前日期?
SELECT CURRENT_DATE();
7. 如何获取MySQL的版本?
SELECT VERSION();
8. 什么是触发器,MySQL都有哪些触发器?
触发器是指一段代码,当触发某个事件时,自动执行这些代码
MySQL 数据库中有六种触发器:
Before Insert,After Insert,Before Update,After Update,Before Delete,After Delete
使用场景:
可以通过数据库中的相关表实现级联更改
实时监控表中字段的更改做出相应处理
9. MySQL显示表前 50 行
SELECT * FROM tablename LIMIT0,50;
limit 0,50 等价于limit 50
10. 如何连接MySQL服务端、关闭连接?
参考答案
连接:使用指令 mysql -u -p -h -P (-u:指定用户名 -p:指定密码 -h:主机 -P:端口) 连接 MySQL 服务端
关闭:使用指令 exit 或 quit
11. int(10)、char(16)、varchar(16)、datetime、text的意义?
int(10) 表示字段是 INT 类型,显示长度是 10
char(16)表示字段是固定长度字符串,长度为 16
varchar(16) 表示字段是可变长度字符串,最大长度为 16
datetime 表示字段是时间类型
text 表示字段是字符串类型,能存储大字符串,最多存储 65535 字节数据
12. 说说你知道的MySQL存储引擎
InnoDB
默认事务型引擎,被广泛使用的存储引擎
数据存储在共享表空间,即多个表和索引都存储在一个表空间中,可通过配置文件修改
主键查询的性能高于其他类型的存储引擎
内部做了很多优化,如:从磁盘读取数据时会自动构建hash索引,插入数据时自动构建插入缓冲区
通过一些机制和工具支持真正的热备份
支持崩溃后的安全恢复
支持行级锁
支持外键
MyISAM
拥有全文索引、压缩、空间函数
不支持事务和行级锁、不支持崩溃后的安全恢复
表存储在两个文件:MYD 和 MYI
设计简单,某些场景下性能很好,例如获取整个表有多少条数据,性能很高
其他表引擎:Archive、Blackhole、CSV、Memory
memory存储引擎,顾名思义是在内存中存储所有的数据,它具有以下两个明显特征: 内存中存储数据,非常高速;mysql关闭后所有数据消失,mysql启动时会创建空表;
12. 共享表空间VS独立表空间
优点:
可以将表空间分成多个文件存放到各个磁盘上(表空间文件大小不受表大小的限制,如一个表可以分布在不同的文件上)。数据和文件放在一起方便管理。
缺点:
所有的数据和索引存放到一个文件中,虽然可以把一个大文件分成多个小文件,但是多个表及索引在表空间中混合存储,这样对于一个表做了大量删除操作后表空间中将会有大量的空隙,特别是对于统计分析,日值系统这类应用最不适合用共享表空间。
. 每个表都有自已独立的表空间。
2. 每个表的数据和索引都会存在自已的表空间中。
3. 可以实现单表在不同的数据库中移动。
4. 空间可以回收(除drop table操作处,表空不能自已回收)
a. Drop table操作自动回收表空间,如果对于统计分析或是日值表,删除大量数据后可以通过:alter table TableName engine=innodb; 回缩不用的空间。
b. 对于使innodb-plugin的Innodb使用turncate table也会使空间收缩。
c. 对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。
缺点: 表过大的话,相比较之下,使用独占表空间的效率以及性能会更高一点。
13. 说一说MySQL中的锁机制
数据库中数据是供多用户共享访问,锁是保证数据并发访问的一致性、有效性的一种机制。
锁的分类
按粒度分:
表级锁:粒度最大的一种锁,表示对当前操作的整张表加锁。开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低
行级锁:粒度最小的一种锁,表示只针对当前操作的行进行加锁。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高
页级锁:粒度介于行级锁和表级锁中间的一种锁。开销、加锁时间和并发度界于表锁和行锁之间;会出现死锁
按操作分:
读锁(共享锁):针对同一份数据,多个读取操作可以同时进行,不互相影响
写锁(排它锁):当前写操作没有完成前,会阻断其他写锁和读锁
MySQL 不同的存储引擎支持不同的锁机制
InnoDB 存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁
MyISAM 和 MEMORY 存储引擎采用的是表级锁(table-level locking)
BDB 存储引擎采用的是页面锁(page-level locking),也支持表级锁
14. 说一说MySQL中的事务
事务具有四大特性(ACID):
原子性(Atomic):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样
一致性(Consistency):在事务开始之前和事务结束以后, 数据库的完整性没有被破坏
隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)
持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
MYSQL 事务处理的方法:
1、用 BEGIN, ROLLBACK, COMMIT来实现
BEGIN 开始事务
ROLLBACK 事务回滚
COMMIT 事务确认
15. MySQL中TEXT数据类型的最大长度
TINYTEXT:256 bytes
TEXT:65,535 bytes(64kb)
MEDIUMTEXT:16,777,215 bytes(16MB)
LONGTEXT:4,294,967,295 bytes(4GB)
16. MySQL中有哪些时间字段?
DATETIME:8 bytes
TIMESTAMP:4 bytes
DATE:4 bytes
TIME:3 bytes
YEAR:1 byte
日期格式
DATETIME:YYYY-MM-DD HH:MM:SS 年月日,时分秒
TIMESTAMP:YYYY-MM-DD HH:MM:SS
DATE:YYYY-MM-DD
TIME:HH:MM:SS
YEAR:YYYY
DATETIME:1000-01-01 00:00:00
最小值
TIMESTAMP:1970-01-01 00:00:01 UTC
DATE:1000-01-01
TIME:-838:59:59
YEAR:1901
17. MySQL中DATETIME和TIMESTAMP的区别
存储精度都为秒
区别:
DATETIME 的日期范围是 1001——9999 年;TIMESTAMP 的时间范围是 1970——2038 年
DATETIME 存储时间与时区无关;TIMESTAMP 存储时间与时区有关,显示的值也依赖于时区
DATETIME 的存储空间为 8 字节;TIMESTAMP 的存储空间为 4 字节
DATETIME 的默认值为 null;TIMESTAMP 的字段默认不为空(not null),默认值为当前时间(CURRENT_TIMESTAMP)
18. FLOAT和DOUBLE的区别是什么?
FLOAT 类型数据可以存储至多 8 位十进制数,占 4 字节
DOUBLE 类型数据可以存储至多 18 位十进制数,占 8字节
19. Mysql驱动程序是什么?
Mysql 提供给 Java 编程语言的驱动程序就是这样 mysql-connector-java-5.1.18.jar 包
针对不同的数据库版本,驱动程序包版本也不同
不同的编程语言,驱动程序的包形式也是不一样的
驱动程序主要帮助编程语言与 MySQL 服务端进行通信,如果连接、关闭、传输指令与数据等
20. Innodb引擎有什么特性?
插入缓冲(insert buffer)
二次写(double write)
自适应哈希索引(ahi)
预读(read ahead)
21. 使用过MySQL的存储过程吗?介绍一下
存储过程(Stored Procedure)是数据库中一种存储复杂程序,供外部程序调用的一种数据库对象
是一段 SQL 语句集,被编译保存在数据库中
可命名并传入参数来调用执行
可在存储过程中加入业务逻辑和流程
可在存储过程中创建表,更新数据,删除数据等
可通过把 SQL 语句封装在容易使用的单元中,简化复杂的操作
22. 什么是索引?什么场景使用?
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息
使用索引目的是加快检索表中数据
使用场景:
中到大数据量表适合使用索引
小数据量表,大部分情况全表扫描效率更高
特大数据量表,建立和使用索引的代价会随之增大,适合使用分区或分库
23. 索引的种类有哪些?
普通索引:最基本的索引,没有任何约束限制。
唯一索引:和普通索引类似,但是具有唯一性约束,可以有 null
主键索引:特殊的唯一索引,不允许有 null,一张表最多一个主键索引
组合索引:多列值组成一个索引,用于组合搜索,效率大于索引合并
全文索引:对文本的内容进行分词、搜索
覆盖索引:查询列要被所建的索引覆盖,不必读取数据行
24. 如何创建与删除索引?
建单个字段索引的语法:CREATE INDEX 索引名 on 表名(字段名)
创建联合索引的语法:CREATE INDEX 索引名 on 表名(字段名1,字段名2)
索引命名格式一般可以这样:idx_表名_字段名。注意有长度限制
删除索引:DROP INDEX 索引名 ON 表名
index 替换成 unique 或 primary key,分别代表唯一索引和主键索引
25. 索引对性能有哪些影响?
优点:
1.加快检索数据的速度
2.提高查询速度.查询优化器就是根据索引。可以加快表连接,排序,分组的速度
3.唯一索引,能保证数据的唯一性
缺点:
1。索引的创建和维护耗时随着数据量的增加而增加
2.对表中数据进行增删改时,索引也要动态维护,降低了数据的维护速度
3.增大磁盘占用
26. MySQL创建和使用索引的注意事项?
1.适合创建索引的列是出现在 WHERE 或 ON 子句中的列,而不是出现在 SELECT 关键字后的列
3.对字符串列进行索引,可制定一个前缀长度,节省索引空间
4.避免创建过多的索引,索引会额外占用磁盘空间,降低写操作效率
5.主键尽可能选择较短的数据类型,可减少索引的磁盘占用,提高查询效率
6.MySQL 在数据量较小的情况可能会不使用索引,因为全表扫描比使用索引速度更快
索引失效的几种情况。
1.LIKE 查询,%在前不到索引
2.关键词 or 前面的条件中的列有索引,后面的没有,所有列的索引都不会被用到
3.类型自动转换
4.联合索引要遵从 最左前缀原则,否则不会用到索引
5.<>
6.列涉及到运算,不会使用索引
27. 创建MySQL联合索引应该注意什么?
联合索引要遵从最左前缀原则,否则不会用到索引
AND 只要用到了最左侧a列,和顺序无关 都会使用 索引
Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。
如索引是 index (a,b,c),可以支持 a 或 a,b 或 a,b,c 3种组合进行查找,但不支持 b,c 进行查找
28. 列值为NULL时,查询是否会用到索引?
MySQL 中存在 NULL 值的列也是走索引的
计划对列进行索引,应尽量避免把它设置为可空,因为这会让 MySQL 难以优化引用了可空列的查询,同时增加了引擎的复杂度
29. 以下语句是否会使用索引?
SELECTFROMuserWHEREYEAR(cdate)<2007;
不会,因为列涉及到运算,不会使用索引
30. 以下三条sql 如何只建一条索引?
WHERE a=1ANDb=1 WHEREb=1 WHEREb=1O RDERBY timeDESC
以顺序 b,a,time 建立联合索引,CREATE INDEX idx_b_a_time ON table(b,a,time)。
新 MySQL 版本会优化 WHERE 子句后面的列顺序,以匹配联合索引顺序
31. LIKE 后的%和_代表什么?
% 代表 0 或更多字符
_ 代表 1 个字符
32. 与Oracle相比,Mysql有什么优势?
Mysql 是开源软件、无需付费
操作简单、部署方便,用户可以根据应用的需求去定制数据库
Mysql 的引擎是插件式
33. MySQL有哪些常用函数?
34. MyISAM索引与InnoDB索引的区别?
InnoDB 索引是聚集索引,MyISAM 索引是非聚集索引,InnoDB 的主键索引的叶子节点存储着行数据,主键索引非常高效
MyISAM 索引的叶子节点存储的是行数据地址,需要再寻址一次才能得到数据
InnoDB 非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效
覆盖索引
using index表示字段的信息直接从索引树中获得
:将被查询的字段,建立到联合索引里去。
35. Mysql中exists和in的区别
下面将主查询的表称为外表;子查询的表称为内表。exists 与 in 的主要区别如下:
子查询使用 exists,会先进行主查询,将查询到的每行数据循环带入子查询校验是否存在,过滤出整体的返回数据;子查询使用 in,会先进行子查询获取结果集,然后主查询匹配子查询的结果集,返回数据
外表内表相对大小情况不一样时,查询效率不一样:两表大小相当,in 和 exists 差别不大;内表大,用 exists 效率较高;内表小,用 in 效率较高。
不管外表与内表的大小,not exists 的效率一般要高于 not in,跟子查询的索引访问类型有关。
37. MySQL如何进行慢SQL优化?
通过慢查询日志去寻找哪些 SQL 执行效率低
使用 explain 获取低效率 SQL 的执行计划
结合 SQL 与执行计划,进行分析与优化
引起 SQL 查询很慢的原因与解决办法:
1、没有索引。解决办法:
根据 where 和 order by 使用比较频繁的字段创建索引,提高查询效率
索引不宜过多,单表最好不要超过 6 个。索引过多会导致占用存储空间变大;insert、update 变慢
删除未使用的索引
2、索引未生效。解决办法:
避免在 where 子句中对字段进行 null 值判断,创建表默认值是 NULL。尽量使用 NOT NULL,或使用特殊值,如 0、-1
(1)查询中包含可为NULL的列,对Mysql来说更难优化,因为可为NULL的列使得索引,索引统计和值比较都更复杂。
(2)含NULL复合索引无效.
(3)可为NULL的列会使用更多的存储空间,在Mysql中也需要特殊处理。
(4)当可为NULL的列被索引时,每个索引记录需要一个额外的字节,在MyISAM里甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引。
避免在 where 子句中使用 != 或 <> 操作符, MySQL 只有对以下操作符才使用索引:<、<=、=、>、>=、BETWEEN、IN、非 % 开头的 LIKE
避免在 where 子句中使用 or 来连接条件,可以使用 UNION 进行连接
能用 union all 就不用 union,union 过滤重复数据要耗费更多的 CPU 资源
避免部分 like 查询,如 '%ConstXiong%'
避免在索引列上使用计算、函数
in 和 not in 慎用,能用 between 不要用 in
select 子句中避免使用 *
3、单表数据量太大。解决办法:
分页查询(在索引上完成排序分页操作、借助主键进行关联)
单表数据过大,进行分库分表
考虑使用非关系型数据库提高查询效率
全文索引场景较多,考虑使用 ElasticSearch、solr
提升性能的一些技巧:
尽量使用数字型字段
只需要一行数据时使用 limit 1
索引尽量选择较小的列
不需要的数据在 GROUP BY 之前过滤掉
大部分时候 exists、not exists 比 in、not in 效率(除了子查询是小表的情况使用 in 效率比 exists 高)
不确定长度的字符串字段使用 varchar/nvarchar,如使用 char/nchar 定长存储会带来空间浪费
不要使用 select *,去除不需要的字段查询
避免一次性查询过大的数据量
使用表别名,减少多表关联解析时间
多表 join 最好不超过 5 个,视图嵌套最好不超过 2 个
or 条件查询可以拆分成 UNION 多个查询
count(1) 比 count(*) 有效
判断是否存在数据使用 exists 而非 count,count 用来获取数据行数
38. 说一些索引失效的情况
如果条件中有 or,即使其中有部分条件是索引字段,也不会使用索引
复合索引,查询条件不使用索引前面的字段,后续字段也将无法使用索引
以 % 开头的 like 查询
索引列的数据类型存在隐形转换
where 子句里对索引列有数学运算
where 子句里对索引列使用函数
MySQL 引擎估算使用全表扫描要比使用索引快,则不使用索引
39. 这种情况,ID 是几?
一张自增表里总共有 7 条数据,删除了最后 2 条,重启 MySQL 数据库,又插入了 1 条,此时 ID 是几?
表的存储引擎如果是 MyISAM,ID = 8
表的存储引擎如果是 InnoDB,ID = 6
InnoDB 表只会把自增主键的最大 ID 记录在内存中,所以重启之后会导致最大 ID 丢失
40. 说一说 MySQL 的行锁和表锁
MyISAM 只支持表锁;InnoDB 支持表锁和行锁,默认为行锁。
表锁:开销小,加锁快,不会出现死锁。锁粒度大,发生锁冲突的概率最高,并发量最低。
行锁:开销大,加锁慢,会出现死锁。锁粒度小,发生锁冲突的概率小,并发度最高。
41. 说一说MySQL的乐观锁和悲观锁?
乐观锁:每次去获取数据的时候都认为别人不会修改,不会上锁,但是在提交修改的时候会判断一下在此期间别人有没有修改这个数据。
悲观锁:每次去获取数据的时候都认为别人会修改,每次都会上锁,阻止其他线程获取数据,直到这个锁释放。
MySQL 的乐观锁需要自己实现。一般在表里面添加一个 version 字段,每次修改成功值加 1;每次修改其他字段值的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否一致,如果不一致就可以返回失败也可以进行重试。
MySQL 的悲观锁,表锁,行锁
42. MySQL中如何避免死锁?
尽量以相同的顺序来访问索引记录和表
业务上能够接受幻读和不可重复读,考虑降低锁的级别到 Read committed,降低死锁发生的概率
添加合理的索引,走索引避免为每一行加锁,降低死锁的概率
在事务中一次锁定所需要的所有资源,如 MyISAM 引擎的表锁
避免大事务,尽量将大事务拆成多个小事务来处理
尽量避免同时并发对同一表进行读写操作,特别是执行加锁且操作数据量较大的语句
设置锁等待超时参数
43. 举例说明数据库死锁
1.加锁顺序不一致可能会导致死锁:事务 1 持有 id = 1 的行锁,更新 id = 2 的行数据;事务 2 持有 id = 2 的行锁,更新 id = 1的行数据
2.在范围查询更新时,加锁是一条记录一条记录挨个加锁的,数据行被加锁顺序不一样也会导致死锁