2021数据库考试题及答案 mysql题目和详细答案
1.非聚簇索引一定会回表查询吗?不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询 。
举个简单的例子:假设我们在员工表的年龄上建立了索引,那么当进行的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询.
selectagefromemployeewhereage <20
2.Mysql删除表几种方式?有什么区别?
- delete : 仅删除表数据,支持where条件过滤,支持回滚 。记录日志 。因此比较慢 。delete from links;
- truncate: 仅删除所有数据,不支持where条件过滤,不支持回滚 。不记录日志,效率高于delete 。truncate table links;
- drop:删除表数据同时删除表结构 。将表所占的空间都释放掉 。删除效率最高 。drop table links;
- 唯一键冲突 假设执行 SQL 的时候 user 表 id = 10,此时在内存中的自增 id 为11,此时发生唯一键冲突写库失败,则 user 表没有 id = 10 这条记录,之后 id 从11开始写入,因此 id 是不连续的 。
- 事务回滚 假设同时需要对 user、staff 表进行写库操作,执行 SQL 的时候 user 表 id = 10,此时在内存中的自增 id 为11;staff 表 id = 20,此时内存中的自增 id 为21,一旦事务执行失败,事务回滚,写库失败,则 user 表没有 id = 10 这条记录,staff 表没有 id = 20 这条记录,user 表从11开始写入,staff 表从21开始写入,如此产生 id 不连续的现象 。
- 批量写库操作 对于批量插入数据的语句,MySQL 有一个批量申请自增 id 的策略: 1. 语句执行过程中,第一次申请自增 id,会分配 1 个;2. 1 个用完以后,这个语句第二次申请自增 id,会分配 2 个; 3. 2 个用完以后,还是这个语句,第三次申请自增 id,会分配 4 个; 依此类推,同一个语句去申请自增 id,每次申请到的自增 id 个数都是上一次的两倍 。假设批量往 user 表中写入四条记录,则这四条记录将分为三次申请id,第一次分配到 id = 1,第二次分配到 id = 2、3,第三次分配到 id = 4、5、6、7,当批量写入四条记录之后,id = 1、2、3、4将会入库,但是 id = 5、6、7就被废弃了,下一个 id 从8开始 。
下面是常用存储引擎的适用环境 。
- MyISAM:5.1及之前版本默认存储引擎 。如果应用是以读操作和插入操作为主,=只有很少的更新和删除操作,并且对事务的完整性、并发性要求不是很高,那么选择这个存 储引擎是非常适合的 。MyISAM 是在 Web、数据仓储和其他应用环境下最常使用的存储引擎 之一 。
- InnoDB:5.5及之后默认存储引擎 。用于事务处理应用程序,支持外键 。如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询以外,还包括很多的更新、 删除操作,那么 InnoDB 存储引擎应该是比较合适的选择 。InnoDB 存储引擎除了有效地降低 由于删除和更新导致的锁定,还可以确保事务的完整提交(Commit)和回滚(Rollback),对于类似计费系统或者财务系统等对数据准确性要求比较高的系统,InnoDB 都是合适的选 择 。
- MEMORY:将所有数据保存在 RAM 中,在需要快速定位记录和其他类似数据的环境 下,可提供极快的访问 。MEMORY 的缺陷是对表的大小有限制,太大的表无法 CACHE 在内存中,其次是要确保表的数据可以恢复,数据库异常终止后表中的数据是可以恢复的 。MEMORY 表通常用于更新不太频繁的小表,用以快速得到访问结果 。
- MERGE:用于将一系列等同的 MyISAM 表以逻辑方式组合在一起,并作为一个对象引用它们 。MERGE 表的优点在于可以突破对单个 MyISAM 表大小的限制,并且通过将不同 的表分布在多个磁盘上,可以有效地改善MERGE表的访问效率 。这对于诸如数据仓储等VLDB 环境十分适合 。
选择原则,根据选定的存储引擎,确定如何选择合适的数据类型,下面的选择方法按存储引擎分类 :
- MyISAM 数据存储引擎和数据列
- MEMORY存储引擎和数据列MEMORY数据表目前都使用固定长度的数据行存储,因此无论使用CHAR或VARCHAR列都没有关系 。两者都是作为CHAR类型处理的 。
- InnoDB 存储引擎和数据列建议使用 VARCHAR类型对于InnoDB数据表,内部的行存储格式没有区分固定长度和可变长度列(所有数据行 都使用指向数据列值的头指针),因此在本质上,使用固定长度的CHAR列不一定比使 用可变长度VARCHAR列简单 。因而,主要的性能因 是数据行使用的存储总量 。由于 CHAR 平均占用的空间多于VARCHAR,因此使用VARCHAR来最小化需要处理的数据行的存储总量和年盘I/O是比较好的 。
mysql的字符集包括字符集(CHARACTER)和校对规则(COLLATION)两个概念 。字符集是用来定义mysql存储字符串的方式,校对规则则是定义了比较字符串的方式 。字符集和校对规则是一对多的关系, MySQL支持30多种字符集的70多种校对规则 。
每个字符集至少对应一个校对规则 。可以用SHOW COLLATION LIKE ‘utf8%’;命令查看相关字符集的校对规则
7.如何选择字符集?对数据库来说,字符集更加重要,因为数据库存储的数据大部分都是各种文字,字符集对数据库的存储,处理性能,以及日后系统的移植,推广都会有影响 。mysql5.6目前支持几十种字符集,包括ucs2,utf16,utf16le,utf32,utf8和utf8mb4等Unicode字符集 。根据应用的需求,考虑以下几方面的因素 。
- 满足应用支持语言的需求,如果应用要处理各种各样的文字,或者将发布到使用不同语言的国家或地区,就应该选择Unicode字符集 。对Mysql来说,目前就是utf8,如果要存储emoji表情需使用utf8mb4 。
- 如果应用中涉及已有数据的导入,就要充分考虑数据库字符集对已有数据的兼容性 。假如已有数据是gbk文字,如果选择gb2312-80为数据库字符集,就很有可能出现某些文字无法正确导入的问题
- 如果数据库只支持一般中文,数据量很大,性能要求也很高,那就应该选择双字节长编码的中文字符集,比如gbk 。因为,相对于utf8而言,gbk比较“小”,每个汉字只占2个字节,而utf8汉字编码需要3个字节,这样可以减少磁盘I/O,数据库Cache以及网络传输的时间,从而提高性能 。相反,如果应用主要处理英文字符,仅有少量汉字数据,那么选择utf8更好,因为gbk,ucs2,utf16的西文字符编码都是2个字节,会造成很多不必要的开销 。
- 如果数据库需要做大量的字符运算,如比较,排序等,那么选择定长字符集可能更好,因为定长字符集的处理速度要比变长字符集的处理速度快 。
- 如果所有客户端程序都支持相同的字符集,则应该优先选择该字符集作为数据库字符集,这样可以避免因字符集转换带来的性能开销和数据损失 。
8.如何查询最后一行记录?
select*fromlinksorderbyiddesclimit1;
9.sql注入问题?SQL注入攻击(SQL Injection),简称为注入攻击,SQL注入,被广泛用于非法获取网站控制权 。这是在应用程序的数据库层中发生的安全漏洞 。在设计程序中,忽略了对输入字符串中包含的SQL命令的检查,并且将数据库误认为是要运行的常规SQL命令,这导致数据库受到攻击,从而可能导致盗窃,修改和删除数据,并进一步导致网站嵌入恶意代码,植入后门程序的危害等 。注射位置包括
- 表单提交,主要是POST请求,还有GET请求 。
- URL参数提交,主要是GET请求参数 。
- Cookie参数的提交 。
- HTTP请求标头中的一些可修改值,例如Referer,User_Agent等 。
- 一些边缘输入点,例如.mp3文件的某些文件信息 。
- 数据库信息泄漏:泄漏用户存储在数据库中的私人信息 。作为数据存储中心,各种类型的私人信息通常存储在数据库中 。SQL注入攻击能导致这些隐私信息透明于攻击者 。
- 篡改网页:通过操作数据库来篡改特定网页 。
- 网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击 。
- 数据库被恶意操作:数据库服务器受到攻击,数据库系统管理员帐户被篡改 。
- 服务器受远程控制,并安装了后门 。经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统 。
- 破坏硬盘数据并使整个系统瘫痪 。
- 所有查询语句都使用数据库提供的参数化查询接口,并且参数化语句使用参数,而不是将用户输入变量嵌入SQL语句中 。几乎所有当前的数据库系统都提供参数化的SQL语句执行接口 。使用此接口可以有效地防止SQL注入攻击 。String sql=”SELECT * FROM user WHERE username=? AND password=?”; //使用?代替参数,预先设置好sql格式,就算在输入sql关键字也不会被sql识别PreparedStatement pstat=conn.prepareStatement(sql);pstat.setString(1,username); //设置问号的值pstat.setString(2,password);pstat.executeQuery();
- 对进入数据库的特殊字符(’”<>&*;等)进行转义处理,或编码转换 。
- 确认每个数据的类型 。例如,数字数据必须是数字,并且数据库中的存储字段必须与int类型相对应 。
- 应严格规定数据长度,以防在一定程度上正确执行较长的SQL注入语句 。
- 网站每个数据层的编码是统一的 。建议使用UTF-8编码 。上下层编码不一致可能会导致某些过滤模型被绕过 。
- 严格限制网站用户数据库的操作权限,并向该用户提供只能满足其工作要求的权限,从而最大程度地减少了注入攻击对数据库的危害 。
- 阻止网站显示SQL错误消息,例如类型错误,字段不匹配等,以防止攻击者使用这些错误消息进行判断 。
- 在网站发布之前,建议使用一些专业的SQL注入检测工具来及时检测和修补这些SQL注入漏洞 。
本文使用一张名为 t_goods 的数据表,该表用来记录商品信息,它的记录如下:
+----+---------------+-----------------+-------------+---------+---------+---------------------+| id | t_category_id | t_category| t_name| t_price | t_stock | t_upper_time|+----+---------------+-----------------+-------------+---------+---------+---------------------+| 1|1| 女装/女士精品| T恤| 39.90| 1000|2020-11-1000:00:00 || 2|1| 女装/女士精品| 连衣裙| 79.90| 2500|2020-11-1000:00:00 || 3|1| 女装/女士精品| 卫衣| 79.90| 1500|2020-11-1000:00:00 || 4|1| 女装/女士精品| 牛仔裤| 89.90| 3500|2020-11-1000:00:00 || 5|1| 女装/女士精品| 百褶裙| 29.90|500|2020-11-1000:00:00 || 6|1| 女装/女士精品| 呢绒外套| 399.90| 1200|2020-11-1000:00:00 || 7|2| 户外运动| 自行车| 399.90| 1000|2020-11-1000:00:00 || 8|2| 户外运动| 山地自行车 |1399.90| 2500|2020-11-1000:00:00 || 9|2| 户外运动| 登山杖| 59.90| 1500|2020-11-1000:00:00 ||10|2| 户外运动| 骑行装备| 399.90| 3500|2020-11-1000:00:00 ||11|2| 户外运动| 户外运动外套| 799.90|500|2020-11-1000:00:00 ||12|2| 户外运动| 滑板| 499.90| 1200|2020-11-1000:00:00 |+----+---------------+-----------------+-------------+---------+---------+---------------------+
向 t_goods 数据表中插入两条名称为空字符串,上架时间为 NULL 的数据记录 。mysql> INSERT INTO t_goods-> (t_category_id, t_category, t_name, t_price, t_stock, t_upper_time)-> VALUES-> (1, '女装/女士精品', '', 399.90, 1200, NULL),-> (2, '户外运动', '', 499.90, 1200, NULL);Query OK, 2 rows affected (0.01 sec)Records: 2Duplicates: 0Warnings: 0
SQL语句执行成功 。匹配 NULL 值例如,查询 t_goods 数据表中上架时间为 NULL的 数据 。
mysql> SELECT id, t_category, t_name, t_price-> FROM t_goods-> WHERE t_upper_time IS NULL;+----+-----------------+-------------+---------+| id | t_category| t_name| t_price |+----+-----------------+-------------+---------+| 13 | 女装/女士精品||399.90 || 14 | 户外运动||499.90 |+----+-----------------+-------------+---------+2 rows in set (0.00 sec)
IS NOT NULL 与 IS NULL 相反,用于查询数据表中某个字段的值不是 NULL 的数据记录 。例如,查询 t_goods 数据表中上架时间不为 NULL 的数据 。
mysql> SELECT id, t_category, t_name, t_price-> FROM t_goods-> WHERE t_upper_time IS NOT NULL;+----+----------------+-------------+---------+| id | t_category| t_name| t_price |+----+----------------+-------------+---------+|1 | 女装/女士精品| T恤|39.90 ||2 | 女装/女士精品| 连衣裙|79.90 ||3 | 女装/女士精品| 卫衣|79.90 ||4 | 女装/女士精品| 牛仔裤|89.90 ||5 | 女装/女士精品| 百褶裙|29.90 ||6 | 女装/女士精品| 呢绒外套|399.90 ||7 | 户外运动| 自行车|399.90 ||8 | 户外运动| 山地自行车| 1399.90 ||9 | 户外运动| 登山杖|59.90 || 10 | 户外运动| 骑行装备|399.90 || 11 | 户外运动| 户外运动外套 |799.90 || 12 | 户外运动| 滑板|499.90 |+----+----------------+-------------+---------+12 rows in set (0.00 sec)
匹配空字符串例如,查询 t_goods 数据表中名称为空字符串的数据 。mysql> SELECT id, t_category, t_name, t_price-> FROM t_goods-> WHERE t_name = '';+----+-----------------+-------------+---------+| id | t_category| t_name| t_price |+----+-----------------+-------------+---------+| 13 | 女装/女士精品||399.90 || 14 | 户外运动||499.90 |+----+-----------------+-------------+---------+2 rows in set (0.00 sec)
使用“<>”或“!=”运算符能够查询数据表中某个字段的值不是空字符串的数据 。例如,查询 t_goods 数据表中名称不是空字符串的数据 。mysql> SELECT id, t_category, t_name, t_price-> FROM t_goods-> WHERE t_name <> '';+----+----------------+-------------+---------+| id | t_category| t_name| t_price |+----+----------------+-------------+---------+|1 | 女装/女士精品| T恤|39.90 ||2 | 女装/女士精品| 连衣裙|79.90 ||3 | 女装/女士精品| 卫衣|79.90 ||4 | 女装/女士精品| 牛仔裤|89.90 ||5 | 女装/女士精品| 百褶裙|29.90 ||6 | 女装/女士精品| 呢绒外套|399.90 ||7 | 户外运动| 自行车|399.90 ||8 | 户外运动| 山地自行车| 1399.90 ||9 | 户外运动| 登山杖|59.90 || 10 | 户外运动| 骑行装备|399.90 || 11 | 户外运动| 户外运动外套|799.90 || 12 | 户外运动| 滑板|499.90 |+----+----------------+-------------+---------+12 rows in set (0.00 sec)
11.InnoDB默认事务隔离级别?如何查看事务隔离级别?- 可重复读取(REPEATABLE-READ)
- 查看事务隔离级别:
因此,可以通过索引先查询出id字段,再通过主键id字段,查询行中的字段数据,即通过再次查询提供MySQL查询速度 。
13.如何避免回表?
- 尽量使用主键
- 如果必须使用辅助索引,那么尽量避免使用*,直接列出所需列名使用索引覆盖 。如果所需数据仅包含辅助索引列,那么它将不读取主键,因为辅助索引包含辅助索引列的值
覆盖索引的定义与注意事项
如果一个索引覆盖(包含)了所有需要查询的字段的值,这个索引就是覆盖索引 。因为索引中已经包含了要查询的字段的值,因此查询的时候直接返回索引中的字段值就可以了,不需要再到表中查询,避免了对主键索引的二次查询,也就提高了查询的效率 。
要注意的是,不是所有类型的索引都可以成为覆盖索引的 。因为覆盖索引必须要存储索引的列值,而哈希索引、空间索引和全文索引等都不存储索引列值,索引MySQL只能使用B-Tree索引做覆盖索引 。
另外,当发起一个被索引覆盖的查询(索引覆盖查询)时,在explain(执行计划)的Extra列可以看到【Using Index】的信息 。
覆盖索引的优点
1.索引条目通常远小于数据行的大小,因为覆盖索引只需要读取索引,极大地减少了数据的访问量 。
2.索引是按照列值顺序存储的,对于IO密集的范围查找会比随机从磁盘读取每一行数据的IO小很多 。
3.一些存储引擎比如MyISAM在内存中只缓存索引,数据则依赖操作系统来缓存,因此要访问数据的话需要一次系统调用,使用覆盖索引则避免了这一点 。
4.由于InnoDB的聚簇索引,覆盖索引对InnoDB引擎下的数据库表特别有用 。因为InnoDB的二级索引在叶子节点中保存了行的主键值,如果二级索引能够覆盖查询,就避免了对主键索引的二次查询 。
15.视图的优缺点?优点1.简化了操作:此时我们完全不用关心视图是怎么处理数据的,我们只需要知道如何使用这个结果集即可,视图相当于一个中间层 。
2.更加安全:比如我们可以让用户有权去访问某个视图,但是不能访问原表,这样就可以起到保护原表中某些数据的作用 。
3.管理权限是无法细致到某一个列的,通过视图,则很容易实现 。
4.降低耦合:假如我们以后要修改原表的结构,那么我们可以通过修改视图的定义即可,而不用修改应用程序,对访问者是不会造成影响的,一般来说,这样代价会更小 。
缺点1.性能:从数据库视图查询数据可能会很慢,特别是如果视图是基于其他视图创建的 。
2.表依赖关系:将根据数据库的基础表创建一个视图 。每当更改与其相关联的表的结构时,都必须更改视图 。
16.主键和唯一索引区别?主键是一种约束,唯一索引是一种索引,两者在本质上是不同的 。
- 主键创建后一定包含一个唯一性索引,唯一性索引并不一定就是主键 。
- 唯一性索引列允许空值,而主键列不允许为空值 。
- 主键列在创建时,已经默认为非空值 + 唯一索引了 。
- 主键可以被其他表引用为外键,而唯一索引不能 。
- 一个表最多只能创建一个主键,但可以创建多个唯一索引 。
- 主键和唯一索引都可以有多列 。
- 主键更适合那些不容易更改的唯一标识,如自动递增列、身份证号等 。
- 在 RBO 模式下,主键的执行计划优先级要高于唯一索引 。两者可以提高查询的速度 。
总体来说:主键相当于一本书的页码,索引相当于书的目录 。
其实主键和索引都是键,不过主键是逻辑键,索引是物理键,意思就是主键不实际存在,而索引实际存在在数据库中,主键一般都要建,主要是用来避免一张表中有相同的记录,索引一般可以不建,但如果需要对该表进行查询操作,则最好建,这样可以加快检索的速度 。
17.如何随机获取一条记录?
select * from posts ORDER BY rand() LIMIT 1;
18.查看当前表有哪些索引?show index from posts;
19.什么情况下索引不生效?- 使用不等于查询
- NULL值
- 列参与了数学运算或者函数 。
- 在字符串like时左边是通配为.比如 %xxx 。
- 当mysql分析全表扫描比使用索引快的时候不使用索引 。
- 当使用联合索引,前面一个条件为范围查询,后面的即使符合最左前缀原则,也无法使用 引.
多版本并发控制(Multiversion concurrency control,MCC 或 MVCC),是数据库管理系统常用的一种并发控制,也用于程序设计语言实现事务内存 。
乐观并发控制和悲观并发控制都是通过延迟或者终止相应的事务来解决事务之间的竞争条件来保证事务的可串行化;这两种并发控制机制确实能够从根本上解决并发事务的可串行化的问题,但是其实都是在解决写冲突的问题,两者区别在于对写冲突的乐观程度不同(悲观锁也能解决读写冲突问题,但是性能就一般了) 。而在实际使用过程中,数据库读请求是写请求的很多倍,我们如果能解决读写并发的问题的话,就能更大地提高数据库的读性能,而这就是多版本并发控制所能做到的事情 。与悲观并发控制和乐观并发控制不同的是,MVCC是为了解决读写锁造成的多个、长时间的读操作饿死写操作问题,也就是解决读写冲突的问题 。MVCC 可以与前两者中的任意一种机制结合使用,以提高数据库的读性能 。
数据库的悲观锁基于提升并发性能的考虑,一般都同时实现了多版本并发控制 。不仅是MySQL,包括Oracle、PostgreSQL等其他数据库系统也都实现了MVCC,但各自的实现机制不尽相同,因为MVCC没有一个统一的实现标准 。
总的来说,MVCC的出现就是数据库不满用悲观锁去解决读-写冲突问题,因性能不高而提出的解决方案 。
实现方式MVCC的实现,是通过保存数据在某个时间点的快照来实现的 。每个事务读到的数据项都是一个历史快照,被称为快照读,不同于当前读的是快照读读到的数据可能不是最新的,但是快照隔离能使得在整个事务看到的数据都是它启动时的数据状态 。而写操作不覆盖已有数据项,而是创建一个新的版本,直至所在事务提交时才变为可见 。
当前读和快照读什么是MySQL InnoDB下的当前读和快照读?
- 当前读像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁 。
- 快照读像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是未提交读和串行化级别,因为未提交读总是读取最新的数据行,而不是符合当前事务版本的数据行 。而串行化则会对所有读取的行都加锁 。
适用场景
- 解决读-写冲突的无锁并发控制 。
- 与上面两者结合,提升它们的读性能 。
- 可以解决脏读,幻读,不可重复读等事务问题,更新丢失问题除外 。
- client和server建立连接,client发送sql至server(对应连接器这一过程)
- server如果在查询缓存中发现了该sql,则直接使用查询缓存的结果返回给client,如果查询缓存中没有,则进入下面的步骤(对应查询缓存这一过程,8.0这一过程已经不存在了,8.0完全抛弃了这个功能)
- server对sql进行语法分析,识别出sql里面的字符串是否符合标准,比如select关键字不能写错(对应分析器这一过程)
- server对sql进行语义分析,识别出sql里面的字符串的具体意思是什么,比如T1是表名,C1是列名(对应分析器这一过程 。3、4步其实解析的过程,这个解析的过程是分析器的工作不是优化器的工作)
- server确定sql的执行路径,比如走索引还是全表,多表连接时哪张表先走哪张表后走,当你的where条件的可读性和效率有冲突时mysql内部还会自动进行优化,也就是大家理解的重写where子句(对应优化器这一过程)
- server对执行sql的用户进行权限检查,比如对表是否有权限执行(对应执行器这一过程)
- server执行该sql语句,发送结果给client(对应执行器这一过程)
如果表 T1 中没有字段 C1,而执行select * from T1 where C1=1会报错不存在C1这个列,这个过程对应上面第4个过程,对应分析器这一过程
如果用户对T1表没有权限,而执行select * from T1 where C1=1会报错对表T1没有权限,这个过程对应上面第6个过程,对应执行器这一过程
22.聊聊select 语句执行计划!我们都知道用explain xxx分析sql语句的性能,但是具体从explain的结果怎么分析性能以及每个字段的含义你清楚吗?这里我做下总结记录,也是供自己以后参考 。
首先需要注意:MYSQL 5.6.3以前只能EXPLAIN SELECT; MYSQL5.6.3以后就可以EXPLAIN SELECT,UPDATE,DELETEexplain结果示例:
mysql> explain select * from staff;+----+-------------+-------+------+---------------+------+---------+------+------+-------+| id | select_type | table | type | possible_keys | key| key_len | ref| rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+------+-------+|1 | SIMPLE| staff | ALL| NULL| NULL | NULL| NULL |2 | NULL|+----+-------------+-------+------+---------------+------+---------+------+------+-------+1 row in set
先上一个官方文档表格的中文版:这是explain结果的各个字段,分别解释下含义:
1. idSQL查询中的序列号 。
id列数字越大越先执行,如果说数字一样大,那么就从上往下依次执行 。2. select_type查询的类型,可以是下表的任何一种类型:
DEPENDENT 意味着使用了关联子查询 。
3. table查询的表名 。不一定是实际存在的表名 。可以为如下的值:
- <unionM,N>: 引用id为M和N UNION后的结果 。
- <derivedN>: 引用id为N的结果派生出的表 。派生表可以是一个结果集,例如派生自FROM中子查询的结果 。
- <subqueryN>: 引用id为N的子查询结果物化得到的表 。即生成一个临时表保存子查询的结果 。
system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,unique_subquery,index_subquery,range,index,ALL除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引 。
- 1、system
- 2、const
- 3、eq_ref
eq_ref可用于使用’=’操作符作比较的索引列 。比较的值可以是常量,也可以是使用在此表之前读取的表的列的表达式 。
相对于下面的ref区别就是它使用的唯一索引,即主键或唯一索引,而ref使用的是非唯一索引或者普通索引 。eq_ref只能找到一行,而ref能找到多行 。
- 4、ref
ref可用于使用’=’或'<=>’操作符作比较的索引列 。
- 5、 fulltext
- 6、ref_or_null
eg.SELECT * FROM ref_tableWHERE key_column=expr OR key_column IS NULL;
- 7、index_merge
- 8、unique_subquery
- 9、index_subquery
- 10、range
SELECT * FROM tbl_nameWHERE key_column BETWEEN 10 and 20;SELECT * FROM tbl_nameWHERE key_column IN (10,20,30);
- 11、index
# 此表见有一个name列索引 。# 因为查询的列name上建有索引,所以如果这样type走的是indexmysql> explain select name from testa;+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+| id | select_type | table | type| possible_keys | key| key_len | ref| rows | Extra|+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+|1 | SIMPLE| testa | index | NULL| idx_name | 33| NULL |2 | Using index |+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+1 row in set# 因为查询的列cusno没有建索引,或者查询的列包含没有索引的列,这样查询就会走ALL扫描,如下:mysql> explain select cusno from testa;+----+-------------+-------+------+---------------+------+---------+------+------+-------+| id | select_type | table | type | possible_keys | key| key_len | ref| rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+------+-------+|1 | SIMPLE| testa | ALL| NULL| NULL | NULL| NULL |2 | NULL|+----+-------------+-------+------+---------------+------+---------+------+------+-------+1 row in set# 包含有未见索引的列mysql> explain select * from testa;+----+-------------+-------+------+---------------+------+---------+------+------+-------+| id | select_type | table | type | possible_keys | key| key_len | ref| rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+------+-------+|1 | SIMPLE| testa | ALL| NULL| NULL | NULL| NULL |2 | NULL|+----+-------------+-------+------+---------------+------+---------+------+------+-------+1 row in set
- 12、all
5. partitions版本5.7以前,该项是explain partitions显示的选项,5.7以后成为了默认选项 。该列显示的为分区表命中的分区情况 。非分区表该字段为空(null) 。
6. possible_keys查询可能使用到的索引都会在这里列出来
7. key查询真正使用到的索引 。select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个 。
8. key_len查询用到的索引长度(字节数) 。如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查询不一定都能使用到所有的列,用多少算多少 。留意下这个列的值,算一下你的多列索引总长度就知道有没有使用到所有的列了 。
key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中 。9. ref如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func
10. rows(重要)rows 也是一个重要的字段 。这是mysql估算的需要扫描的行数(不是精确值) 。这个值非常直观显示 SQL 的效率好坏, 原则上 rows 越少越好.
11. filtered这个字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数 。这个字段不重要
12. extra(重要)EXplain 中的很多额外的信息会在 Extra 字段显示, 常见的有以下几种内容:
- distinct:在select部分使用了distinc关键字
- Using filesort:当 Extra 中有 Using filesort 时, 表示 MySQL 需额外的排序操作, 不能通过索引顺序达到排序效果. 一般有 Using filesort, 都建议优化去掉, 因为这样的查询 CPU 资源消耗大.
# 例如下面的例子:mysql> EXPLAIN SELECT * FROM order_info ORDER BY product_name G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: order_infopartitions: NULLtype: indexpossible_keys: NULLkey: user_product_detail_indexkey_len: 253ref: NULLrows: 9filtered: 100.00Extra: Using index; Using filesort1 row in set, 1 warning (0.00 sec)我们的索引是KEY `user_product_detail_index` (`user_id`, `product_name`, `productor`)但是上面的查询中根据 product_name 来排序, 因此不能使用索引进行优化, 进而会产生 Using filesort.如果我们将排序依据改为 ORDER BY user_id, product_name, 那么就不会出现 Using filesort 了. 例如:mysql> EXPLAIN SELECT * FROM order_info ORDER BY user_id, product_name G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: order_infopartitions: NULLtype: indexpossible_keys: NULLkey: user_product_detail_indexkey_len: 253ref: NULLrows: 9filtered: 100.00Extra: Using index1 row in set, 1 warning (0.00 sec)
- Using index“覆盖索引扫描”, 表示查询在索引树中就可查找所需数据, 不用扫描表数据文件, 往往说明性能不错
- Using temporary查询有使用临时表, 一般出现于排序, 分组和多表 join 的情况, 查询效率不高, 建议优化.
前言: 网上关于一张mysql表最多可以创建多少个索引?基本就是两种答案,一种是不限制,一种是16列, 我认为16的由来应该网上传着传着给扭曲, 因为mysql的单个索引最多能包括16列,但是这个是一个索引包含几列的答案而不是一张可以建多少个索引.真的是误导人啊!
因为mysql的一些限制跟具体存储引擎有关,为此以下只列出我们最常用的innoDB和myisam,其他存储引擎的具体限制可以去官网找.- innoDB: 最多创建1017列, 最多64个二级索引, 单个索引最多包含16列, 索引最大长度767字节(其实行格式为REDUNDANT,COMPACT最高为767字节,但行格式为DYNAMIC,COMPRESSED最高可达为3072字节), 行大小最大65536字节
- mysiam: 最多4096列, 最多64个二级索引, 单个索引最多包含16列, 索引最大长度1000字节, 行大小最大65536字节
- innoDB限制的官方文档: https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html
- myisam限制的官方文档: https://dev.mysql.com/doc/refman/8.0/en/myisam-storage-engine.html
24.为什么最好建立一个主键?主键是数据库确保数据行在整张表唯一性的保障,即使业务上本张表没有主键,也建议添加一个自增长的ID列作为主键.设定了主键之后,在后续的删改查的时候可能更加快速以及确保操作数据范围安全.
25.字段为什么要求建议为not null?MySQL官网这样介绍:
NULL columns require additional space in the rowto record whether their values are NULL. For MyISAM tables, each NULL columntakes one bit extra, rounded up to the nearest byte.null值会占用更多的字节,且会在程序中造成很多与预期不符的情况.
- 很多表都包含可为NULL(空值)的列,即使应用程序并不需要保存NULL 也是如此,这是因为可为NULL 是列的默认属性 。通常情况下最好指定列为NOT NULL, 除非真的需要存储NULL 值 。
- 如果查询中包含可为NULL 的列,对MySQL来说更难优化,因为可为NULL 的列 使得索引、 索引统计和值比较都更复杂 。可为 N ULL的列会使用更多的存储空间,在MySQL里也需要特殊处理 。当可为NULL的列被索引时,每个索引记录需要一个额 外的字节,在MyISAM 里甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引 。
- 通常把可为NULL 的列改为NOT NULL 带来的性能提升比较小,所以(调优时)没有 必要首先在现有schema中查找井修改掉这种情况,除非确定这会导致问题 。但是,如果计划在列上建索引,就应该尽扯避免设计成可为 NULL 的列 。
- 当然也有例外,例如值得一提的是,lnnoDB 使用单独的位 (bit) 存储NULL 值,所以对于稀疏数据 有很好的空间效率 。但这一点不适用千MyISAM 。
27.视图是什么?对比普通表优势?视图(View)是一种虚拟存在的表,对于使用视图的用户来说基本上是透明的 。视图并 不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时 动态生成的 。
视图相对于普通的表的优势主要包括以下几项 。
- 简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集 。
- 安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能 限制到某个行某个列,但是通过视图就可以简单的实现 。
- 数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加 列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问 者的影响 。
推荐阅读
- 2021未来可期文案 表达未来可期的句子
- 2016数据库安装教程 sql2016安装教程图解
- 送给老公的生日祝福语简短2021
- 考上大学的祝福的话 升大学贺词祝福语
- 2021十大耐玩的单机游戏 僵尸世界大战单机可以玩吗
- 结婚邀请短信参考,这么写甜死了!
- 将excel导入sql数据库的方法 sql导入数据库命令
- 科2考试技巧 科2考试技巧介绍
- 2021最火的美颜相机 手机美颜相机哪个好用
- 云数据库和普通数据库 mysql代理服务器