MySQL表类型 存储引擎 的选择


Posted in MySQL onNovember 11, 2021

1、查看当前数据库支出的存储引擎

方法1:

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

ERROR:
No query specified

方法2:

(Value 显示为“DISABLED”的记录表示支持该存储引擎,但是数据库启动的时候被禁用。)

mysql> show variables like 'have%';
+------------------------+----------+
| Variable_name          | Value    |
+------------------------+----------+
| have_compress          | YES      |
| have_crypt             | NO       |
| have_dynamic_loading   | YES      |
| have_geometry          | YES      |
| have_openssl           | DISABLED |
| have_profiling         | YES      |
| have_query_cache       | YES      |
| have_rtree_keys        | YES      |
| have_ssl               | DISABLED |
| have_statement_timeout | YES      |
| have_symlink           | YES      |
+------------------------+----------+
11 rows in set, 1 warning (0.00 sec)

2、ENGINE={存储引起类型}  创建表的时候,设置存储引擎

mysql> create table a(
    -> i bigint(20) not null auto_increment,
    -> primary key (i)
    -> ) engine=myisam default charset=gbk;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    3
Current database: test

Query OK, 0 rows affected (1.33 sec)

3、alter able tablename engine={存储引起类型} 修改表为其他存储引擎

mysql> alter table a engine=innodb;
Query OK, 0 rows affected (1.70 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table a \G;
*************************** 1. row ***************************
       Table: a
Create Table: CREATE TABLE `a` (
  `i` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`i`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.14 sec)

3.1 常用存储引擎的对比

特点 MyISAM  InnoDB MEMORY MERGE NDB
存储限制 有  64TB 没有
事务安全   支持      
锁机制 表锁 行锁 表锁 表锁 表锁
B 树索引 支持 支持 支持 支持 支持
哈希索引     支持   支持
全文索引 支持        
集群索引   支持      
数据缓存   支持 支持   支持
索引缓存 支持 支持 支持 支持 支持
数据可压缩   支持        
空间使用   N/A
内存使用 中等
批量插入的速度
支持外键   支持      

3.2 常用存储引擎学习(MyISAM、InnoDB、MEMORY 和 MERGE)

MyISAM:

默认的MySQL存储引擎,不支持事务和外键

优点:访问速度快

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

.frm (存储表定义)

.MYD (MYData,存储数据)

.MYI (MYIndex,存储索引)

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

InnoDB:

处理效率较差,占用较多的空间用来保留数据和索引

优点:具有提交、回滚、奔溃恢复能力的事务安全、唯一支持外键的存储引擎

自动增长列:InnoDB 表的自动增长列可以手工插入,但是插入的值如果是空或者 0,则实际插入的将是自动增长后的值

mysql> create table autoincre_demo(
    -> i smallint not null auto_increment,
    -> name varchar(10),primary key(i)
    -> )engine=innodb;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    5
Current database: test

Query OK, 0 rows affected (1.19 sec)

mysql> insert into autoincre_demo values(1,"121"),(0,"dddf"),(null,"fdf");
Query OK, 3 rows affected (0.59 sec)
Records: 3  Duplicates: 0  Warnings: 0

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

alter table tabename auto_increment=n 设置自动增长列的初始值(此值默认从1开始)

可以使用 LAST_INSERT_ID()查询当前线程最后插入记录使用的值。如果一次插入了多条记录,那么返回的是第一条记录使用的自动增长值。

下面的例子演示了使用 LAST_INSERT_ID()的情况:

mysql> insert into autoincre_demo(name) values('3');
Query OK, 1 row affected (0.36 sec)

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

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

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

外键约束:

在创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引。

下面是样例数据库中的两个表,country 表是父表,country_id 为主键索引,city 表是子表,country_id 字段对 country 表的 country_id 有外键。

mysql> create table country(
    -> country_id smallint unsigned not null auto_increment,
    -> country varchar(50) not null,
    -> last_update timestamp not null default current_timestamp on update current_timestamp,
    -> primary key(country_id)
    -> )engine=innodb default charset=utf8;

Query OK, 0 rows affected (0.86 sec)
mysql> CREATE TABLE city (
    -> city_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    -> city VARCHAR(50) NOT NULL,
    -> country_id SMALLINT UNSIGNED NOT NULL,
    -> last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    -> PRIMARY KEY (city_id),
    -> KEY idx_fk_country_id (country_id),
    -> CONSTRAINT `fk_city_country` FOREIGN KEY (country_id) REFERENCES country (country_id) ON
    -> DELETE RESTRICT ON UPDATE CASCADE
    -> )ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (3.22 sec)

 在创建索引的时候,可以指定在删除、更新父表时,对子表进行的相应操作,包 RESTRICT、CASCADE、SET NULL 和 NO ACTION

  • RESTRICT NO ACTION 相同,是指限制在子表有关联记录的情况下父表不能更新
  • CASCADE 表示父表在更新或者删除时,更新或者删除子表对应记录;
  • SET NULL 则表示父表在更新或者删除的时候,子表的对应字段被 SET NULL
mysql> select * from country;
+------------+---------+---------------------+
| country_id | country | last_update         |
+------------+---------+---------------------+
|          1 | AAA     | 2021-06-16 15:09:22 |
+------------+---------+---------------------+
1 row in set (0.00 sec)

mysql> select * from city;
+---------+------+------------+---------------------+
| city_id | city | country_id | last_update         |
+---------+------+------------+---------------------+
|      10 | bb   |          1 | 2021-06-16 15:11:45 |
+---------+------+------------+---------------------+
1 row in set (0.00 sec)

mysql> delete from country where country_id = 1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`city`, CONSTRAINT `fk_city_country` FOREIGN KEY (`country_id`) REFERENCES `country` (`country_id`) ON UPDATE CASCADE)

mysql> update country set country_id = 10000 where country_id = 1;
Query OK, 1 row affected (0.62 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from country;
+------------+---------+---------------------+
| country_id | country | last_update         |
+------------+---------+---------------------+
|      10000 | AAA     | 2021-06-16 15:13:35 |
+------------+---------+---------------------+
1 row in set (0.00 sec)

mysql> select * from city
    -> ;
+---------+------+------------+---------------------+
| city_id | city | country_id | last_update         |
+---------+------+------------+---------------------+
|      10 | bb   |      10000 | 2021-06-16 15:11:45 |
+---------+------+------------+---------------------+
1 row in set (0.00 sec)

在导入多个表的数据时,如果需要忽略表之前的导入顺序,可以暂时关闭外键的检查;同样,在执行 LOAD DATA ALTER TABLE 操作的时候,可以通过暂时关闭外键约束来加快处理的速度,关闭的命令是“SET FOREIGN_KEY_CHECKS = 0;”,执行完成之后,通过执行“SETFOREIGN_KEY_CHECKS = 1;”语句改回原状态。

查看表外键信息:show create table 或者 show table status 命令

mysql> show table status like 'city' \G;
*************************** 1. row ***************************
           Name: city
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 1
 Avg_row_length: 16384
    Data_length: 16384
Max_data_length: 0
   Index_length: 16384
      Data_free: 0
 Auto_increment: 11
    Create_time: 2021-06-16 15:02:17
    Update_time: 2021-06-16 15:13:35
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.43 sec)

ERROR:
No query specified

 存储方式:

  •   (1)、使用共享表空间存储:表的表结构保存在.frm文件中,数据+索引存在 innodb_data_home_dir innodb_data_file_path 定义的表空间中,可以是多个文件
  •   (2)、使用多表空间存储:表的表结构也保存在.frm文件中,数据+索引单独存在.ibd中;如果是分区表,则每个分区对应单独的.ibd文件,文件名是:“表名+分区名”,可以在创建分区的时候指定每个分区的数据文件的位置,以此来将表的 IO 均匀分布在多个磁盘上

 MEMORY:

使用存在内存中的内容来创建表

每个 MEMORY 表只实际对应一个磁盘文件,格式是.frm

优点:访问速度快(数据存储在内存中),并且默认使用HASH索引,服务关闭则数据丢失

mysql> CREATE TABLE tab_memory ENGINE=MEMORY
    -> SELECT city_id,city,country_id
    -> FROM city GROUP BY city_id;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    12
Current database: test

Query OK, 1 row affected (0.62 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from tab_memory;
+---------+------+------------+
| city_id | city | country_id |
+---------+------+------------+
|      10 | bb   |      10000 |
+---------+------+------------+
1 row in set (0.00 sec)

mysql> show table status like 'tab_memory' \G
*************************** 1. row ***************************
           Name: tab_memory
         Engine: MEMORY
        Version: 10
     Row_format: Fixed
           Rows: 1
 Avg_row_length: 155
    Data_length: 520320
Max_data_length: 65011650
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2021-06-16 15:28:58
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_unicode_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

给表创建索引的时候可以指定索引类型是HASH或是BTREE

mysql> create index mem_hash using hash on tab_memory(city_id);
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    13
Current database: test

Query OK, 1 row affected (0.63 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> show index from tab_memory \G;
*************************** 1. row ***************************
        Table: tab_memory
   Non_unique: 1
     Key_name: mem_hash
 Seq_in_index: 1
  Column_name: city_id
    Collation: NULL
  Cardinality: 1
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: HASH
      Comment:
Index_comment:
1 row in set (0.32 sec)

ERROR:
No query specified

mysql> drop index mem_hash on tab_memory;
Query OK, 1 row affected (0.31 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> create index mem_hash using btree on tab_memory(city_id);
Query OK, 1 row affected (0.16 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> show index from tab_memory \G;
*************************** 1. row ***************************
        Table: tab_memory
   Non_unique: 1
     Key_name: mem_hash
 Seq_in_index: 1
  Column_name: city_id
    Collation: A
  Cardinality: NULL
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
1 row in set (0.00 sec)

ERROR:
No query specified

MERGE:

此存储殷勤是一组MyISAM表的组合

MERGE 类型的表可以进行查询、更新、删除的操作,这些操作实际上是对内部的实际的 MyISAM 表进行的。

对于 MERGE 类型表的插入操作,是通过INSERT_METHOD 子句定义插入的表,可以有 3 个不同的值,使用 FIRST 或 LAST 值使得插入操作被相应地作用在第一或最后一个表上,不定义这个子句或者定义为 NO,表示不能对这个 MERGE 表执行插入操作。

可以对 MERGE 表进行 DROP 操作,这个操作只是删除 MERGE 的定义,对内部的表没有任何的影响。

存储文件:一个.frm 文件存储表定义,另一个.MRG 文件包含组合表的信息,包括 MERGE 表由哪些表组成、插入新的数据时的依据

mysql> create table payment_2020(
    -> 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.25 sec)

mysql>  create table payment_2021(
    -> 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.54 sec)

mysql> CREATE TABLE payment_all(
    -> country_id smallint,
    -> payment_date datetime,
    -> amount DECIMAL(15,2),
    -> INDEX(country_id)
    -> )engine=merge union=(payment_2020,payment_2021) INSERT_METHOD=LAST;
Query OK, 0 rows affected (0.47 sec)

分别向2020和2021中插入数据,并查询

mysql> insert into payment_2020 values(1,'2020-06-01',100000),(2,'2020-06-15',150000);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into payment_2021 values(1,'2021-04-20',35000),(2,'2021-06-15',220000);
Query OK, 2 rows affected (0.03 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from payment_2020;
+------------+---------------------+-----------+
| country_id | payment_date        | amount    |
+------------+---------------------+-----------+
|          1 | 2020-06-01 00:00:00 | 100000.00 |
|          2 | 2020-06-15 00:00:00 | 150000.00 |
+------------+---------------------+-----------+
2 rows in set (0.00 sec)

mysql> select * from payment_2021;
+------------+---------------------+-----------+
| country_id | payment_date        | amount    |
+------------+---------------------+-----------+
|          1 | 2021-04-20 00:00:00 |  35000.00 |
|          2 | 2021-06-15 00:00:00 | 220000.00 |
+------------+---------------------+-----------+
2 rows in set (0.00 sec)

mysql> select * from payment_all;
+------------+---------------------+-----------+
| country_id | payment_date        | amount    |
+------------+---------------------+-----------+
|          1 | 2020-06-01 00:00:00 | 100000.00 |
|          2 | 2020-06-15 00:00:00 | 150000.00 |
|          1 | 2021-04-20 00:00:00 |  35000.00 |
|          2 | 2021-06-15 00:00:00 | 220000.00 |
+------------+---------------------+-----------+
4 rows in set (0.00 sec)

可以发现,payment_all 表中的数据是 payment_2020 payment_2021 表的记录合并后的结果集

下面向 MERGE 表插入一条记录,由于 MERGE 表的定义是 INSERT_METHOD=LAST,就会向最后一个表中插入记录,所以虽然这里插入的记录是 2006 年的,但仍然会写到 payment_2021表中。

mysql> insert into payment_all values(3,'2020-03-30',12333131);
Query OK, 1 row affected (0.31 sec)

mysql> select * from payment_all;
+------------+---------------------+-------------+
| country_id | payment_date        | amount      |
+------------+---------------------+-------------+
|          1 | 2020-06-01 00:00:00 |   100000.00 |
|          2 | 2020-06-15 00:00:00 |   150000.00 |
|          1 | 2021-04-20 00:00:00 |    35000.00 |
|          2 | 2021-06-15 00:00:00 |   220000.00 |
|          3 | 2020-03-30 00:00:00 | 12333131.00 |
+------------+---------------------+-------------+
5 rows in set (0.00 sec)

mysql> select * from payment_2021;
+------------+---------------------+-------------+
| country_id | payment_date        | amount      |
+------------+---------------------+-------------+
|          1 | 2021-04-20 00:00:00 |    35000.00 |
|          2 | 2021-06-15 00:00:00 |   220000.00 |
|          3 | 2020-03-30 00:00:00 | 12333131.00 |
+------------+---------------------+-------------+
3 rows in set (0.00 sec)

mysql> select * from payment_2020;
+------------+---------------------+-----------+
| country_id | payment_date        | amount    |
+------------+---------------------+-----------+
|          1 | 2020-06-01 00:00:00 | 100000.00 |
|          2 | 2020-06-15 00:00:00 | 150000.00 |
+------------+---------------------+-----------+
2 rows in set (0.00 sec)

到此这篇关于MySQL表类型 存储引擎 的选择的文章就介绍到这了,更多相关MySQL表类型 存储引擎内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
Mysql 如何批量插入数据
Apr 06 MySQL
mysql查询的控制语句图文详解
Apr 11 MySQL
浅谈mysql执行过程以及顺序
May 12 MySQL
MySql存储过程之逻辑判断和条件控制
May 26 MySQL
MySQL的安装与配置详细教程
Jun 26 MySQL
MySQL开启事务的方式
Jun 26 MySQL
MYSQL如何查看进程和kill进程
Mar 13 MySQL
MySQL慢查询优化解决问题
Mar 17 MySQL
一文了解MYSQL三大范式和表约束
Apr 03 MySQL
MySQL普通表如何转换成分区表
May 30 MySQL
MySQL8.0 Undo Tablespace管理详解
Jun 16 MySQL
MySQL外键约束(Foreign Key)案例详解
Jun 28 MySQL
一文带你探究MySQL中的NULL
Nov 11 #MySQL
mysql函数全面总结
Nov 11 #MySQL
MYSQL 运算符总结
Nov 11 #MySQL
MySQL 数据类型详情
Nov 11 #MySQL
MYSQL 表的全面总结
Nov 11 #MySQL
MySQL 服务和数据库管理
面试被问select......for update会锁表还是锁行
You might like
Protoss热键控制
2020/03/14 星际争霸
ThinkPHP php 框架学习笔记
2009/10/30 PHP
smarty模板中使用get、post、request、cookies、session变量的方法
2014/04/24 PHP
ThinkPHP3.2.3数据库设置新特性
2015/03/05 PHP
yii通过小物件生成view的方法
2016/10/08 PHP
thinkPHP模板中函数的使用方法示例
2016/11/30 PHP
laravel中Redis队列监听中断的分析
2020/09/14 PHP
js中top/parent/frame概述及案例应用
2013/02/06 Javascript
html5的自定义data-*属性和jquery的data()方法的使用示例
2013/08/21 Javascript
jQuery的显示和隐藏方法与css隐藏的样式对比
2013/10/18 Javascript
JavaScript作用域与作用域链深入解析
2013/12/06 Javascript
jQuery队列操作方法实例
2014/06/11 Javascript
有趣的bootstrap走动进度条
2016/12/01 Javascript
Bootstrap表格使用方法详解
2017/02/17 Javascript
Bootstrap 模态对话框只加载一次 remote 数据的完美解决办法
2017/07/09 Javascript
基于zepto.js实现手机相册功能
2017/07/11 Javascript
详解vue-cli 构建项目 vue-cli请求后台接口 vue-cli使用axios、sass、swiper
2018/05/28 Javascript
在 vue-cli v3.0 中使用 SCSS/SASS的方法
2018/06/14 Javascript
详解vue添加删除元素的方法
2018/06/30 Javascript
使用pm2自动化部署node项目的方法步骤
2019/01/28 Javascript
[43:51]2014 DOTA2国际邀请赛中国区预选赛 Dream Times VS TongFu
2014/05/22 DOTA
python多进程操作实例
2014/11/21 Python
解决PyCharm的Python.exe已经停止工作的问题
2018/11/29 Python
python2.7实现邮件发送功能
2018/12/12 Python
Python 实现判断图片格式并转换,将转换的图像存到生成的文件夹中
2020/01/13 Python
深入探究HTML5的History API
2015/07/09 HTML / CSS
荷兰超市:DEEN
2018/03/14 全球购物
具有防紫外线功能的高性能钓鱼服装:Hook&Tackle
2018/08/16 全球购物
四年大学生活的个人自我评价
2013/12/11 职场文书
酒店个人求职信范文
2014/01/25 职场文书
敲诈同学钱财检讨书范文
2014/11/18 职场文书
爱护环境建议书
2015/09/14 职场文书
2016年父亲节寄语
2015/12/04 职场文书
JMeter对MySQL数据库进行压力测试的实现步骤
2022/01/22 MySQL
css3带你实现3D转换效果
2022/02/24 HTML / CSS
开发者首先否认《遗弃》被取消的传言
2022/04/11 其他游戏