MySQL 5.7 索引、事务与存储引擎

一、MySQL 索引

1、索引介绍

索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物 理地址。在数据十分庞大的时候,索引可以大大加快查询的速度。这是因为使用索引后可以 不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问 相应的数据。索引的作用类似于图书的目录,可以根据目录中的页码快速找到所需的内容。索引是对记录集的多个字段进行排序的方法。在一张表中为一个字段创建一个索引,将 创建另外一个数据结构,包含字段数值以及指向相关记录的指针,然后对这个索引结构进行 排序,允许在该数据上进行二分法排序。 使用索引的副作用是需要额外的磁盘空间。对于 MyISAM 引擎而言,这些索引是被统一保存在一张表中的。如果很多字段都建立了索引,那么会占用大量的磁盘空间,这个文件 将很快到达底层文件系统所能够支持的大小限制。

2、索引的作用

数据库利用各种各样的快速定位技术,能 够大大提高查询效率。特别是当数据量非常大,查询涉及多个表时,使用索引往往能使查询 速度加快成千上万倍。

3、索引的分类

在数据库表中,对字段建立索引可以大大提高查询速度。通过善用这些索引,可以令 MySQL 的查询和运行更加高效。索引是快速搜索的关键。
从逻辑的角度来划分,索引分为普通索引、唯一索引、主键索引、组合索引和全文索引。 这些索引分类的具体解释如下所示

3.1 普通索引

普通索引是最基本的索引,它没有任何限制,也是大多数情况下用到的索引。它有以下 几种创建方式。

直接创建的方式:
CREATE INDEX index_name ON table_name(column(length));
mysql> create index id_index on t1(id);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc t1;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(3)       | NO   | MUL | 0       |       |
| name    | varchar(10)  | NO   |     | NULL    |       |
| score   | decimal(5,2) | YES  |     | NULL    |       |
| address | varchar(50)  | YES  |     | 未知    |       |
| hobby   | int(3)       | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
修改表结构的方式添加索引:
ALTER TABLE table_name ADD INDEX index_name (column(length));
mysql> alter table tmp add index id_index(id);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc tmp;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(3)       | NO   | MUL | 0       |       |
| name    | varchar(10)  | NO   |     | NULL    |       |
| score   | decimal(5,2) | YES  |     | NULL    |       |
| address | varchar(50)  | YES  |     | 未知    |       |
+---------+--------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
创建表结构时,同时创建索引:
CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), INDEX index_name (title(length)) )
mysql> create table new(id int(3),name char(10),address varchar(50),index id_index(id));
Query OK, 0 rows affected (0.01 sec)

mysql> desc new;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(3)      | YES  | MUL | NULL    |       |
| name    | char(10)    | YES  |     | NULL    |       |
| address | varchar(50) | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

3.2 唯一索引

唯一索引与普通索引类似,不同的就是:唯一索引的索引列的值必须唯一,但允许有空 值(注意和主键不同)。如果是组合索引,则列值的组合必须唯一。唯一索引创建方法和普通索引类似。

直接创建唯一索引:
CREATE UNIQUE INDEX index_name ON table_name(column(length));
mysql> create unique index unique_name on new(name);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc new;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(3)      | YES  | MUL | NULL    |       |
| name    | char(10)    | YES  | UNI | NULL    |       |
| address | varchar(50) | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
修改表结构的时候添加唯一索引:
ALTER TABLE table_name ADD UNIQUE index_name (column(length));
mysql> alter table tmp add unique unique_name1(name);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc tmp;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(3)       | NO   | PRI | 0       |       |
| name    | varchar(10)  | NO   | UNI | NULL    |       |
| score   | decimal(5,2) | YES  |     | NULL    |       |
| address | varchar(50)  | YES  |     | 未知    |       |
+---------+--------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
创建表的时候同时创建唯一索引:
CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), UNIQUE indexName (title(length)) );
mysql> create table newtable(id int(4) primary key,name char(15),address varchar(50),unique unique_name(name));
Query OK, 0 rows affected (0.00 sec)

mysql> desc newtable;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(4)      | NO   | PRI | NULL    |       |
| name    | char(15)    | YES  | UNI | NULL    |       |
| address | varchar(50) | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

3.3 主键索引

主键索引是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建 表的时候同时创建主键索引。

CREATE TABLE `table_name` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) NOT NULL , PRIMARY KEY (`id`) );
mysql> create table tt(id int(4),name char(10),address varchar(50),primary key(id));
Query OK, 0 rows affected (0.01 sec)

mysql> desc tt;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(4)      | NO   | PRI | NULL    |       |
| name    | char(10)    | YES  |     | NULL    |       |
| address | varchar(50) | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

3.4 组合索引(最左前缀)

create table user( name varchar(9), age int(3), sex tinyint(1), index user(name, age, sex) );
mysql> create table user(name varchar(9), age int(3), sex tinyint(1), index user(name, age, sex));
Query OK, 0 rows affected (0.01 sec)

mysql> show index from user;    <----查看索引
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          1 | user     |            1 | name        | A         |           0 |     NULL | NULL   | YES  | BTREE      |         |               |
| user  |          1 | user     |            2 | age         | A         |           0 |     NULL | NULL   | YES  | BTREE      |         |               |
| user  |          1 | user     |            3 | sex         | A         |           0 |     NULL | NULL   | YES  | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

3.5 全文索引(FULLTEXT)

在 MySQL5.6 版本以前 FULLTEXT 索引仅可用于 MyISAM 表,在 5.6 之后 innodb 引擎也支持 FULLTEXT 索引,他们可以从 CHAR、VARCHAR 或 TEXT 列中作为 CREATE TABLE 语句的一部分被创建, 或是随后使用 ALTER TABLE 或 CREATEINDEX 被添加。
对于较大的数据集,将资料输入一个没有 FULLTEXT 索引的表中,然后创建索引,其 速度比把资料输入现有 FULLTEXT 索引的速度更快。不过切记对于大容量的数据表,生成 全文索引是一个非常消耗时间、非常消耗硬盘空间的做法

创建表的全文索引:
CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), FULLTEXT (content) );
mysql> create table user1(id int(3) primary key,name varchar(9), age int(3), sex tinyint(1),fulltext(name));
Query OK, 0 rows affected (0.04 sec)

mysql> show index from user1;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user1 |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| user1 |          1 | name     |            1 | name        | NULL      |           0 |     NULL | NULL   | YES  | FULLTEXT   |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
修改表结构添加全文索引:
ALTER TABLE article ADD FULLTEXT index_content(content);
mysql> alter table tt add fulltext index_name(name);
Query OK, 0 rows affected, 1 warning (0.10 sec)
Records: 0  Duplicates: 0  Warnings: 1

mysql> show index from tt;
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tt    |          0 | PRIMARY    |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| tt    |          1 | index_name |            1 | name        | NULL      |           0 |     NULL | NULL   | YES  | FULLTEXT   |         |               |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
直接创建全文索引:
CREATE FULLTEXT INDEX index_content ON article(content);
mysql> create fulltext index index_name on tt(name);
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from tt;
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tt    |          0 | PRIMARY    |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| tt    |          1 | index_name |            1 | name        | NULL      |           0 |     NULL | NULL   | YES  | FULLTEXT   |         |               |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)

3.6 查看索引

两种方式:

  • show index from tablename
mysql> show index from tt;
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tt    |          0 | PRIMARY    |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| tt    |          1 | index_name |            1 | name        | NULL      |           0 |     NULL | NULL   | YES  | FULLTEXT   |         |               |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
  • show keys from tablename;
 mysql> show keys from tt;
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tt    |          0 | PRIMARY    |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| tt    |          1 | index_name |            1 | name        | NULL      |           0 |     NULL | NULL   | YES  | FULLTEXT   |         |               |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)

字段解读:

  • Table:表的名称。
  • Non_unique:如果索引不能包括重复词,则为 0;如果可以,则为 1。
  • Key_name:索引的名称。
  • Seq_in_index:索引中的列序号,从 1 开始。
  • Column_name:列名称。
  • Collation:列以什么方式存储在索引中。在 MySQL 中,有值‘A’(升序)或 NULL(无 分类)。
  • Cardinality:索引中唯一值数目的估计值。通过运行 ANALYZE TABLE 或 myisamchk -a
    可以更新。基数根据被存储为整数的统计数据来计数,所以即使对于小型表,该值也没 有必要是精确的。基数越大,当进行联合时,MySQL
    使用该索引的机会就越大。
  • Sub_part:如果列只是被部分地编入索引,则为被编入索引的字符的数目。如果整列 被编入索引,则为 NULL。
  • Packed:指示关键字如何被压缩。如果没有被压缩,则为 NULL。
  • Null:如果列含有 NULL,则含有 YES。如果没有,则该列含有 NO。
  • Index_type:用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)。
  • Comment:备注

3.7 删除索引

索引在创建之后,是会占用一定的磁盘空间的,因此表内如果有不再使用的索引,从数 据库性能方面考虑,最好是删除无用索引

DROP INDEX 索引名 ON 表名; 
mysql> drop index index_name on tt;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from tt;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tt    |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
ALTER TABLE 表名 DROP INDEX 索引名;
mysql> desc newtable;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(4)      | NO   | PRI | NULL    |       |
| name    | char(15)    | YES  | UNI | NULL    |       |
| address | varchar(50) | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> alter table newtable drop index unique_name;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc newtable;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(4)      | NO   | PRI | NULL    |       |
| name    | char(15)    | YES  |     | NULL    |       |
| address | varchar(50) | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

二、MySQL 事务

1、事务的简介

MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中, 要删除一个人员,即需要删除人员的基本资料,又需要删除和该人员相关的信息,如信箱, 文章等等。这样,这些数据库操作语句就构成一个事务!
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
事务用来管理 insert,update,delete 语句。

2、事务的ACID条件

一般来说,事务是必须满足 4 个条件(ACID):原子性(Atomicity,或称不可分割性)、 一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

  • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不
    会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开 始前的状态,就像这个事务从来没有执行过一样;
  • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的
    资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以 自发性地完成预定的工作;
  • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防
    止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包 括读未提交(Read
    uncommitted)、读提交(read committed)、可重复读(repeatable
    read)和串行化(Serializable);
  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

3、事务的控制语句

在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马 上执行 COMMIT 操作。因此要显式地开启一个事务必须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。

事务控制语句包含:

  • BEGIN 或 START TRANSACTION:显式地开启一个事务;
  • COMMIT:也可以使用 COMMIT WORK,不过二者是等价的。COMMIT 会提交事务, 并使已对数据库进行的所有修改变为永久性的;
  • ROLLBACK:又可以使用 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
  • SAVEPOINT identifier:SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以 有多个 SAVEPOINT;
  • RELEASE SAVEPOINT identifier:删除一个事务的保存点,当没有指定的保存点时, 执行该语句会抛出一个异常;
  • ROLLBACK TO identifier:把事务回滚到标记点;
  • SET TRANSACTION:用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有 READ UNCOMMITTED 、READ COMMITTED 、 REPEATABLE READ 和SERIALIZABLE。

4、事务的处理方法

MYSQL 事务处理主要有两种方法:

(1)用 BEGIN, ROLLBACK, COMMIT 来实现
BEGIN 开始一个事务
ROLLBACK 事务回滚
COMMIT事务确认

(2)直接用 SET 来改变 MySQL 的自动提交模式
SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交

示例

mysql> use school;
Database changed

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into newtable values(1,'shangzhen','nanjing');                                                                 
Query OK, 1 row affected (0.00 sec)

mysql> insert into newtable values(2,'tangyan','shanghai');                                                                  
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> 
mysql> select * from newtable;
+----+-----------+----------+
| id | name      | address  |
+----+-----------+----------+
|  1 | shangzhen | nanjing  |
|  2 | tangyan   | shanghai |
+----+-----------+----------+
2 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into newtable values(3,'shidapeng','hangzhou');
Query OK, 1 row affected (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from newtable;
+----+-----------+----------+
| id | name      | address  |
+----+-----------+----------+
|  1 | shangzhen | nanjing  |
|  2 | tangyan   | shanghai |
+----+-----------+----------+
2 rows in set (0.01 sec)

三、MySQL 存储引擎

在数据库中保存的是一张张有着千丝万缕关系的表,所以表设计的好坏,将直接影响着整个数据库。而在设计表的时候,最关注的一个问题是使用什么存储引擎。 MySQL 中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种都 使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的、不同的功能和能力。通过选择不同的技术,能够获得额外的速度或者功能,从而改善应用的整体性能。

这些不同的技术以及配套的相关功能在 MySQL 中被称作存储引擎(也称作表类型)。 MySQL 默认配置了许多不同的存储引擎,可以预先设置或者在 MySQL 服务器中启用。选择适用于服务器、数据库和表格的存储引擎,可以在存储信息、检索数据时,提供最大的灵活性。

对于 MySQL 来说,它提供了很多种类型的存储引擎(或者说不同的表类型),根据对数据处理的需求,可以选择不同的存储引擎,从而最大限度的利用 MySQL 强大的功能。

在 MySQL 客户端中,使用以下命令可以查看 MySQL 支持的引擎

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)

查看数据库中具体某个表使用的存储引擎:

mysql> show table status from school where name='newtable';
+----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| Name     | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options | Comment |
+----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| newtable | MyISAM |      10 | Dynamic    |    2 |             28 |          56 | 281474976710655 |         2048 |         0 |           NULL | 2020-09-01 19:58:35 | 2020-09-01 19:58:35 | NULL       | utf8_general_ci |     NULL |                |         |
+----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
1 row in set (0.00 sec)

1、MyISAM 存储引擎

MyISAM 存储引擎不支持事务,也不支持外键,特点是访问速度快,对事务完整性没有要求,以 SELECT、INSERT 为主的应用基本都可以使用这个引擎来创建表。

每个 MyISAM 表在磁盘上存储成 3 个文件,其中文件名和表名都相同,但是扩展名分 别为:

  • frm(存储表定义)
  • MYD(MYData,存储数据)
  • MYI(MYIndex,存储索引)

数据文件和索引文件可以放置在不同的目录,平均分配 IO,获取更快的速度。要指定数据文件和索引文件的路径,需要在创建表的时候通过 DATA DIRECTORY 和 INDEX DIRECTORY 语句指定,文件路径需要使用绝对路径。

MyISAM 表还支持 3 种不同的存储格式:

  • 静态(固定长度)表
  • 动态表
  • 压缩表

其中静态表是默认的存储格式。静态表中的字段都是非可变字段,这样每个记录都是固定长度的,这种存储方式的优点是存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多。静态表在数据存储时会根据列定义的宽度定义补足空格,但是在访问的时候并不会得到这些空格,这些空格在返回给应用之前已经去掉。同时需要注意:在某些情况下可能需要返回字段后的空格,而使用这种格式时后面的空格会被自动处理掉。

动态表包含可变字段,记录不是固定长度的,这样存储的优点是占用空间较少,但是频繁的更新、删除记录会产生碎片,需要定期执行 OPTIMIZE TABLE 语句或 myisamchk -r 命令来改善性能,并且出现故障的时候恢复相对比较困难。

压缩表由 myisamchk 工具创建,占据非常小的空间,因为每条记录都是被单独压缩的, 所以只有非常小的访问开支。

2、InnoDB 存储引擎

InnoDB 是一个健壮的事务型存储引擎,这种存储引擎已经被很多互联网公司使用,为 用户操作非常大的数据存储提供了一个强大的解决方案。MySQL 从 5.5.5 版本开始,默认 的存储引擎为 InnoDB。InnoDB 存储引擎还引入了行级锁定和外键约束,在以下场景中使用 InnoDB 存储引擎是最理想的选择:

  • 更新密集的表:InnoDB 存储引擎特别适合处理多重并发的更新请求。
  • 事务:InnoDB 存储引擎是支持事务的标准 MySQL 存储引擎。
  • 自动灾难恢复:与其它存储引擎不同,InnoDB 表能够自动从灾难中恢复。
  • 外键约束:MySQL 支持外键的存储引擎只有 InnoDB。
  • 支持自动增加列 AUTO_INCREMENT 属性。 一般来说,如果需要事务支持,并且有较高的并发读取频率,InnoDB 是不错的选择。

而 MyISAM 和 InnoDB 两种存储引擎的区别主要表现在以下几个方面。

  • InnoDB 支持事务,MyISAM 不支持,这一点是非常重要的。事务是一种高级的处理方
    式,如对一些表中的列进行增删改的过程中只要哪个出错还可以回滚还原,而 MyISAM就不可以。
  • MyISAM 适合查询、插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用。
  • InnoDB 支持外键,MyISAM 不支持。
  • 从 MySQL5.5.5 以后,InnoDB 是默认引擎。
  • MySQL 从 5.6 版本开始 InnoDB 引擎才支持 FULLTEXT 类型的索引。
  • InnoDB 中不保存表的行数,如 select count() from table 时,InnoDB 需要扫描一遍整个表来计算有多少行,但是 MyISAM 只要简单的读出保存好的行数即可。需要注意的 是,当 count()语句包含 where 条件时MyISAM 也需要扫描整个表。
  • 对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM 表中可以 和其他字段一起建立组合索引。
  • 清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表。
  • InnoDB 支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like
    ‘%lee%’;)

修改默认的存储引擎

通过 alter table 修改
alter table user_info engine=MyISAM;
mysql> alter table newtable engine=MYISAM;
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0
通过修改 my.cnf,指定默认存储引擎并重启服务
[root@Mysql /]#vim my.cnf 
default-storage-engine=InnoDB
通过 create table 创建表时指定存储引擎。
create table engineTest(id int) engine=MyISAM;
mysql> create table Test(id int(3)) engine=MyISAM;
Query OK, 0 rows affected (0.00 sec)

mysql> show table status from school where name='Test';
+------+--------+---------+------------+------+----------------+-------------+------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length  | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options | Comment |
+------+--------+---------+------------+------+----------------+-------------+------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| Test | MyISAM |      10 | Fixed      |    0 |              0 |           0 | 1970324836974591 |         1024 |         0 |           NULL | 2020-09-01 20:06:02 | 2020-09-01 20:06:02 | NULL       | utf8_general_ci |     NULL |                |         |
+------+--------+---------+------------+------+----------------+-------------+------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
1 row in set (0.00 sec)
通过 Mysql_convert_table_format 转化存储引擎。
yum -y install perl-DBI perl-DBD-MySQL
/usr/local/mysql/bin/mysql_convert_table_format --user=root --password='123456' --sock=/tmp/mysql.sock auth

猜你喜欢

转载自blog.csdn.net/shengjie87/article/details/108327068