MySQL开发篇(4)表类型(存储引擎)的选择

  一、查看支持的存储引擎以及设置修改存储引擎

  1.查看默认存储引擎:show variables like '%storage_engine%';

  2.查看当前数据库支持的存储引擎:show ENGINES G

  3.查看某个表使用的存储引擎: show create table 表名;

  4.创建新表时指定存储引擎(如果不设置ENGINE则使用默认的存储引擎)

mysql> CREATE TABLE ai(i bigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY(i))
    -> ENGINE=MyISAM DEFAULT CHARSET=gbk;
Query OK, 0 rows affected (0.04 sec)

  5.将一个已经存在的表修改成其他的存储引擎:ALTER TABLE ai ENGINE=innodb;

  二、各种存储引擎的特性

  1.MyISAM

  MyISAM是默认的MySQL插件式存储引擎。如果应用是以读操作和插入操作为主,只有很少的更新操作和删除操作,并且对事务的完整性、并发性要求不是很高,那么选择这个存储引擎是非常适合的。MyISAM是在Web、数据仓储和其他应用环境下最长使用的存储引擎之一。

  MyISAM是MySQL默认的存储引擎。

  MyISAM不支持事务、也不支持外键,其优势是访问的速度快,对事务完整性没有要求或者以SELECT、INSET为主的应用基本上都可以使用MyISAM来创建表。

  每个MyISAM在磁盘上存储成3个文件,扩展名分别是:.frm(存储表定义)、.MYD(MYData,存储数据)、.MYI(MYIndex,存储索引)

  数据文件和索引文件可以防止在不同的目录,平均分布IO,获得更快的速度。

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

  • 静态(固定长度)表: 静态表是默认的存储格式。静态表中的字段都是非变长地段,这样每个记录都是固定长度的,这种存储方式的优点是存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间比动态表多。静态表的数据在存储时会按照列的宽度定义补足空格,但是在应用访问的时候并不会得到这些空格,这些空格在返回应用之前已经去掉。
  • 动态表:动态表中包含变长字段,记录不是固定长度的,这样存储的优点是占用的空间相对较少,但是频繁地更新和删除记录会产生碎片,需要定期执行OPTIMIZE TABLE语句或myisamchk -r命令来改善性能,并且在出现故障时恢复相对比较困难。
  • 压缩表:由myisampack工具创建,占据非常小的磁盘空间。因为每个记录是被单独压缩的,所以只有非常小的访问开支。

  

  2.InnoDB

  InnoDB用于事务处理应用程序,支持外键、如果应用对事务的完整性有比较高的要求,在并发条件下要去数据的一致性,数据操作除了插入和查询以外,还包括很多的更新和删除操作,那么InnoDB是比较合适的选择。InnoDB除了有效地降低由于删除和更新导致的锁定,还可以确保事务的完整提交(Commit)和回滚(Rollback),以及崩溃恢复能力的事务安全,对于类似计费系统或者财务系统等对数据准确性要求比较高的系统,InnoDB都是合适的选择。

  InnoDB不同于其他存储引擎的表的特点:自动增长列、外键约束、存储方式

  (1)自动增长列

  InnoDB表的自动增长列可以手动插入,当插入的值是0或者null时,实际插入的将是自动增长后的值。如果跳跃着插入,则从插入的第一个值开始增长。

  对于InnoDB表,自动增长列必须是索引。如果是组合索引,也必须是组合索引的第一列。

  但是对于MyISAM表,自动增长列可以是组合索引的其他列,这样插入记录后,自动增长列是按照组合索引的前面几列进行排序后递增的。

mysql> create table autoincre_demo
    -> (i smallint not null auto_increment,
    -> name varchar(10),primary key(i)
    -> )engine=innodb;
Query OK, 0 rows affected (0.04 sec)

mysql> insert into autoincre_demo values(1,'1'),(0,'2'),(null,'3');
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from autoincre_demo;
+---+------+
| i | name |
+---+------+
| 1 | 1    |
| 2 | 2    |
| 3 | 3    |
+---+------+
3 rows in set (0.00 sec)

mysql> insert into autoincre_demo values(1,'1'),(0,'2'),(null,'3');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> insert into autoincre_demo values(5,'1'),(0,'2'),(null,'3');
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from autoincre_demo;
+---+------+
| i | name |
+---+------+
| 1 | 1    |
| 2 | 2    |
| 3 | 3    |
| 5 | 1    |
| 6 | 2    |
| 7 | 3    |
+---+------+
6 rows in set (0.00 sec)

mysql> select LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                6 |
+------------------+
1 row in set (0.00 sec)

mysql> insert into autoincre_demo values('5');
ERROR 1136 (21S01): Column count doesn't match value count at row 1
mysql> insert into autoincre_demo values(9,'5');
Query OK, 1 row affected (0.00 sec)

mysql> select LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                6 |
+------------------+
1 row in set (0.00 sec)

mysql> insert into autoincre_demo values(10,'1'),(0,'2'),(null,'3');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|               11 |
+------------------+
1 row in set (0.00 sec)

mysql> show tables;
+----------------+
| Tables_in_tmz  |
+----------------+
| ai             |
| autoincre_demo |
| dept           |
| emp            |
| emp1           |
| salary         |
| settest        |
| t1             |
| t2             |
| t3             |
| t6             |
+----------------+
11 rows in set (0.00 sec)

mysql> drop autoincre_demo;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'autoincre_demo' at line 1
mysql> drop table autoincre_demo;
Query OK, 0 rows affected (0.04 sec)

mysql> show tables;
+---------------+
| Tables_in_tmz |
+---------------+
| ai            |
| dept          |
| emp           |
| emp1          |
| salary        |
| settest       |
| t1            |
| t2            |
| t3            |
| t6            |
+---------------+
10 rows in set (0.00 sec)

mysql> create table autoincre_demo
    -> (d1 smallint not null auto_increment,
    -> d2 smallint not null,
    -> name varchar(10),
    -> index(d2,d1)
    -> )engine=myisam;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into autoincre_demo(d2,name) values(2,'2'),(3,'3'),(4,'4'),(2,'2'),(3,'3'),(4,'4');
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> select * from autoincre_demo;
+----+----+------+
| d1 | d2 | name |
+----+----+------+
|  1 |  2 | 2    |
|  1 |  3 | 3    |
|  1 |  4 | 4    |
|  2 |  2 | 2    |
|  2 |  3 | 3    |
|  2 |  4 | 4    |
+----+----+------+
6 rows in set (0.00 sec)
自动增长列使用举例

  (2)外键约束(TODO)

  MySQL支持外键约束的只有InnoDB。在创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动地创建相应的索引。

  (3)存储方式

  • 使用共享表空间存储:表结构保存在.frm文件中,数据和索引保存在innodb_data_home_dir和innodb_data_file_path定义的表空间中,可以多个文件。
  • 使用多表空间存储:表结构仍然保存在.frm文件中,但是每个表的数据和索引单独保存在.ibd中。如果是个分区表,则每个分区对应单独的.ibd文件。

  

  3.MEMROY

  MEMORY将所有数据保存在RAM中,在需要快速定位记录和其他类似数据的环境下,可 提供极快的访问。MEMORY的缺陷是对表的大小有限制,太大的表无法缓存在内存中,其次是要确保表的数据可以恢复,数据库异常终止后表中的数据是可以恢复的。MEMORY表通常用于更新不太频繁的小表,可以快速得到访问结果。

  MEMORY存储引擎使用存在于内存中的内容来创建表。每个MEMORY表只实际对应一个磁盘文件,格式是.frm。MEMORY类型的表访问非常地块,因为它的数据是放在内存中的,并且默认使用HASH索引,也可以指定使用BTREE索引,但是一旦服务关闭,表中的数据就会丢失掉。

  MEMORY主要用于内容变化不频繁的表,或者作为统计操作的中间结果表,便于高效地对中间结果进行分析并得到最终的统计结果。对MEMORY的表进行更新操作要谨慎,因为数据并没有实际写入到磁盘中,所以一定要对下次重新启动服务后如何获得这些修改后的数据有所考虑。

  

  4.MERGE

  MERGE用于将一系列等同的MyISAM表以逻辑方式组合在一起,并作为一个对象引用它们。MERGE表的优点在于可以突破对单个MyISAM表大小的限制,并且通过将不同的表分布在多个磁盘上,可以有效地改善MERGE表的访问效率。这对于诸如数据仓储等VLDB环境十分适合。

  MERGE存储引擎是一组MyISAM表的组合,这些MyISAM表必须结构完全相同,MERGE表本身并没有数据,对MERGE类型的表可以进行查询、更新、删除操作,这些操作实际上是对内部的MyISAM表进行的。

  在定义MERGE表时,需要声明union和INSERT_METHOD,假如INSERT_METHOD=LAST,那么执行向MERGE表中插入数据时,就会向UNION中最后一个表中插入数据,这也是MERGE表和分区表的区别,MERGE表并不能智能地将记录写到对应的表中,而分区表是可以的。

1.新建两个MyISAM表和一个MERGE表
mysql> create table payment_2006(
    -> country_id smallint,
    -> payment_date datetime,
    -> amount decimal(15,2),
    -> key idx_fk_country_id(country_id)
    -> )engine=myisam;
Query OK, 0 rows affected (0.01 sec)

mysql> create table payment_2007(
    -> country_id smallint,
    -> payment_date datetime,
    -> amount decimal(15,2),
    -> key idx_fk_country_id(country_id)
    -> )engine=myisam;
Query OK, 0 rows affected (0.01 sec)

mysql> create table payment_all(
    -> country_id smallint,
    -> payment_date datetime,
    -> amount decimal(15,2),
    -> INDEX(country_id)
    -> )engine=merge union=(payment_2006, payment_2007) INSERT_METHOD=LAST;
Query OK, 0 rows affected (0.01 sec)

2.分别向两个MyISAM表中插入数据并查看三个表中的内容
mysql> insert into payment_2006 values(1,'2006-05-01',100000),(2,'2006-08-15',150000);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into payment_2007 values(1,'2007-02-20',35000),(2,'2007-07-15',220000);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from payment_2006;
+------------+---------------------+-----------+
| country_id | payment_date        | amount    |
+------------+---------------------+-----------+
|          1 | 2006-05-01 00:00:00 | 100000.00 |
|          2 | 2006-08-15 00:00:00 | 150000.00 |
+------------+---------------------+-----------+
2 rows in set (0.00 sec)

mysql> select * from payment_2007;
+------------+---------------------+-----------+
| country_id | payment_date        | amount    |
+------------+---------------------+-----------+
|          1 | 2007-02-20 00:00:00 |  35000.00 |
|          2 | 2007-07-15 00:00:00 | 220000.00 |
+------------+---------------------+-----------+
2 rows in set (0.00 sec)

mysql> select * from payment_all;
+------------+---------------------+-----------+
| country_id | payment_date        | amount    |
+------------+---------------------+-----------+
|          1 | 2006-05-01 00:00:00 | 100000.00 |
|          2 | 2006-08-15 00:00:00 | 150000.00 |
|          1 | 2007-02-20 00:00:00 |  35000.00 |
|          2 | 2007-07-15 00:00:00 | 220000.00 |
+------------+---------------------+-----------+
4 rows in set (0.00 sec)

3.向MERGE表中插入数据,则可以看到的是向最后的MyISAM表中插入的
mysql> insert into payment_all values(3,'2006-03-31',112200);
Query OK, 1 row affected (0.00 sec)

mysql> select * from payment_all;
+------------+---------------------+-----------+
| country_id | payment_date        | amount    |
+------------+---------------------+-----------+
|          1 | 2006-05-01 00:00:00 | 100000.00 |
|          2 | 2006-08-15 00:00:00 | 150000.00 |
|          1 | 2007-02-20 00:00:00 |  35000.00 |
|          2 | 2007-07-15 00:00:00 | 220000.00 |
|          3 | 2006-03-31 00:00:00 | 112200.00 |
+------------+---------------------+-----------+
5 rows in set (0.00 sec)
MERGE表使用示例

  

原文地址:https://www.cnblogs.com/BigJunOba/p/9590055.html