MySQL数据库表类型 (存储引擎)的选择
小标 2018-03-05 来源 :网络 阅读 1451 评论 0

摘要:MySQL 存储引擎概述

--1.MySQL 存储引擎概述


1.和大多数数据库不同,MySQL 中有一个存储引擎的概念,针对不同的存储需求可以选择最优的存储引擎;


2.其中 InnoDB 和 BDB 提供事务安全表,其他存储引擎都是非事务安全表。


3.创建新表不指定表的存储引擎,则新表是默认存储引擎(InnoDB)的.


4.如果需要修改默认的存储引擎,则可以在参数文件中设置 default-table-type


5.查看当前的默认存储引擎:mysql> show variables like 'table_type';


6.查询当前数据库支持的存储引擎:


1.SHOW ENGINES \G;--查看当前支持哪些存储引擎


2.SHOW VARIABLES LIKE 'have%';--同一


3.show engines;--查看mysql现在已提供什么存储引擎


4.show variables like '%storage_engine%';--查看mysql当前默认的存储引擎


7.修改一个已经存在的存储引擎:alter table [tableName] engine = [engineName];


--问题:MySQL为什么要把InnoDB定为默认的存储引擎?


因为InnoDB存储引擎十分优秀。


--2.各种存储引擎的特性(常用)


--MyISAM


优势:访问速度快


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


.frm(存储表定义);


.MYD(MYData,存储数据);


.MYI (MYIndex,存储索引)。


MyISAM 类型的表提供修复的工具,可以用 CHECK TABLE 语句来检查 MyISAM 表的健康,


并用 REPAIR TABLE 语句修复一个损坏的 MyISAM 表。


表损坏可能导致数据库异常重新启动,需要尽快修复并尽可能地确认损坏的原因。


mysql> check table t_book;
+----------------+-------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------+-------+----------+----------+
| db_book.t_book | check | status | OK |
+----------------+-------+----------+----------+
1 row in set (0.02 sec)


--MyISAM 的表又支持 3 种不同的存储格式,分别是:


 静态(固定长度)表;


 动态表;


 压缩表。


--静态表


静态表是默认的存储格式。


静态表中的字段都是非变长字段,这样每个记录都是固定长度的,


这种存储方式的


--优点是存储非常迅速,容易缓存,出现故障容易恢复;


--缺点是占用的空间通常比动态表多。


静态表的数据在存储的时候会按照列的宽度定义补足空格,


但是在应用访问的时候并不会得到这些空格,这些空格在返回给应用之前已经去掉。


example:
mysql> create table Myisam_char (name char(10)) engine=myisam;
mysql> insert into Myisam_char values('abcde'),('abcde '),(' abcde'),(' abcde ');
mysql> select name,length(name) from Myisam_char;
+---------+--------------+
| name | length(name) |
+---------+--------------+
| abcde | 5 |
| abcde | 5 |
| abcde | 7 |
| abcde | 7 |
+---------+--------------+

4 rows in set (0.00 sec)--插入记录后面的空格都被去掉了,前面的空格保留


--动态表;


动态表中包含变长字段,记录不是固定长度的,这样存储的优点是占用的空间相对较少,


但是频繁地更新删除记录会产生碎片,需要定期执行 OPTIMIZE TABLE 语句


或 myisamchk -r 命令来改善性能,并且出现故障的时候恢复相对比较困难。


--压缩表:


压缩表由 myisampack 工具创建,占据非常小的磁盘空间。


因为每个记录是被单独压缩的,所以只有非常小的访问开支。


--InnoDB


--1.自动增长列


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


LAST_INSERT_ID()查询当前线程最后插入记录使用的值。如果一次插入了多条记录,


那么返回的是第一条记录使用的自动增长值。


example:
mysql> create table autoincre_demo
-> (d1 smallint not null auto_increment,
-> d2 smallint not null,
-> name varchar(10),
-> index(d2,d1)
-> )engine=myisam;
mysql> insert into autoincre_demo(d2,name) values(2,'2'),(3,'3'),(4,'4'),(2,'2'),(3,'3') ,(4,'4');
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.外键约束


当某个表被其他表创建了外键参照,那么该表的对应索引或者主键禁止被删除。


--3.存储方式


--InnoDB 存储表和索引有以下两种方式:


 1.使用共享表空间存储,这种方式创建的表的表结构保存在.frm 文件中,数据和索引


保存在 innodb_data_home_dir 和 innodb_data_file_path 定义的表空间中,可以是多个文件。


 2.使用多表空间存储,这种方式创建的表的表结构仍然保存在.frm 文件中,但是每个


表的数据和索引单独保存在.ibd 中。如果是个分区表,则每个分区对应单独的.ibd


文件,文件名是“表名+分区名”,可以在创建分区的时候指定每个分区的数据文件


的位置,以此来将表的 IO 均匀分布在多个磁盘上。


--注意:即便在多表空间的存储方式下,共享表空间仍然是必须的,InnoDB 把内部数据词典和未作日志放在这个文件中。


--MEMORY


MEMORY 存储引擎使用存在内存中的内容来创建表。每个 MEMORY 表只实际对应一个磁盘文件,格式是.frm。


MEMORY 类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用 HASH 索引,但是一旦服务关闭,表中的数据就会丢失掉。


--给 MEMORY 表创建索引的时候,可以指定使用 HASH 索引还是 BTREE 索引:


mysql> create index mem_hash USING HASH on tab_memory (city_id) ;
mysql> drop index mem_hash on tab_memory;


服务器需要足够内存来维持所有在同一时间使用的 MEMORY 表,


当不再需要 MEMORY 表的内容之时,要释放被MEMORY表使用的内存,


应该执行DELETE FROM或TRUNCATE TABLE,或者整个地删除表(使用 DROP TABLE 操作)。


每个 MEMORY 表中可以放置的数据量的大小,受到 max_heap_table_size 系统变量的约


束,这个系统变量的初始值是 16MB,可以按照需要加大。此外,在定义 MEMORY 表的时候,


可以通过 MAX_ROWS 子句指定表的最大行数。


--MERGE


MERGE 存储引擎是一组 MyISAM 表的组合,这些 MyISAM 表必须结构完全相同,MERGE


表本身并没有数据,对 MERGE 类型的表可以进行查询、更新、删除的操作,这些操作实际


上是对内部的实际的 MyISAM 表进行的。可以对 MERGE 表进行 DROP 操作,


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


mysql> create table payment_2016(
country_id smallint,
payment_date datetime,
amount DECIMAL(15,2),
KEY idx_fk_country_id (country_id)
)engine=myisam;
mysql> create table payment_2017(
country_id smallint,
payment_date datetime,
amount DECIMAL(15,2),
KEY idx_fk_country_id (country_id)
)engine=myisam;
mysql> CREATE TABLE payment_all(
country_id smallint,
payment_date datetime,
amount DECIMAL(15,2),
INDEX(country_id)
)engine=merge union=(payment_2016,payment_2017) INSERT_METHOD=LAST;

-- INSERT_METHOD=LAST 表示将记录插入到payment_all表的最后一行;


--如果插入的时候指定为payment_2016表时,插入操作不会自动将记录放到payment_2016表的后面,而是插入到payment_2017表的后面;


--这也是 MERGE 表和分区表的区别,MERGE 表并不能智能地将记录写到对应的表中,而分区表是可以的。


--3.如何选择合适的存储引擎


参考《常用存储引擎的对比》表;


选择使用哪种存储引擎才是最佳方案也不是绝对的,这需要根据用户各自的应用进行测试,从而得到最适合自己的结果。


MyISAM:是在 Web、数据仓储和其他应用环境下最常使用的存储引擎之一,以读操作和插入操作为主。


InnoDB:对于类似计费系统或者财务系统等对数据准确性要求比较高的系统,InnoDB 都是合适的选择。(InnoDB存储引擎是十分优秀的存储引擎)


MEMORY:将所有数据保存在 RAM 中,在需要快速定位记录和其他类似数据的环境下,可提供极快的访问。


MEMORY 的缺陷是对表的大小有限制,太大的表无法 CACHE 在内存中,


其次是要确保表的数据可以恢复,数据库异常终止后表中的数据是可以恢复的。


MEMORY 表通常用于更新不太频繁的小表,用以快速得到访问结果。


MERGE: 表的优点在于可以突破对单个 MyISAM 表大小的限制,


并且通过将不同的表分布在多个磁盘上,可以有效地改善MERGE表的访问效率。


这对于诸如数据仓储等 VLDB 环境十分适合。


-------------------------------选择合适的数据类型-------------------------------


--1.CHAR与VARCHAR


CHAR 与 VARCHAR的比较


-- CHAR VARCHAR


字符类型 固定长度 可变长度


处理速度 快 慢


缺点 浪费存储空间


(程序需要对行尾空格进行处理)


适用范围 长度变化不大并且


对查询速度有较高要求的数据


--在 MySQL 中,不同的存储引擎对 CHAR 和 VARCHAR 的使用原则有所不同:


1.MyISAM 存储引擎:建议使用固定长度的数据列代替可变长度的数据列。


2.MEMORY 存储引擎:目前都使用固定长度的数据行存储,因此无论使用 CHAR 或 VARCHAR 列都没有关系。两者都是作为 CHAR 类型处理。


3.InnoDB 存储引擎:建议使用 VARCHAR 类型,InnoDB主要的性能因素是数据行使用的存储总量。


--2.TEXT 与 BLOB


BLOB 能用来保存二进制数据,比如照片;


TEXT 只能保存字符数据,比如一篇文章或者日记。


TEXT: TEXT、MEDIUMTEXT、LONGTEXT
BLOB: BLOB、MEDIUMBLOB、LONGBLOB3


BLOB 和 TEXT 值会引起一些性能问题,特别是在执行了大量的删除操作时。


删除操作会在数据表中留下很大的“空洞”,以后填入这些“空洞”的记录在插入的性能上会有影响。


为了提高性能,建议定期使用 OPTIMIZE TABLE 功能对这类表进行碎片整理,避


免因为“空洞”导致性能问题。


example:
mysql> create table t (id varchar(100),context text);
mysql> insert into t values(1,repeat('haha',100)); --使用repeat函数向t表中插入大量数据
mysql> insert into t values(2,repeat('haha',100));
mysql> insert into t values(3,repeat('haha',100));
mysql> insert into t select * from t;


mysql> exit --退出到操作系统下,查看表 t 的物理文件大小


mysql> delete from t where id=1; --从t表中删除id为1的数据;


mysql> exit --再次退出到操作系统下,查看表 t 的物理文件大小


$ du -sh t.* --发现t表的数据量并没有因为删除而减少,存在'空洞'


mysql> OPTIMIZE TABLE t;--OPTIMIZE[??pt?ma?z] 优化


$ du -sh t.* --再次查看t表的大小,可以发现“空洞”空间已经被回收


--使用合成的(Synthetic)索引来提高大文本字段(BLOB 或 TEXT)的查询性能


example:
mysql> create table t (id varchar(100),context blob,hash_value varchar(40));
mysql> insert into t values(1,repeat('beijing',2),md5(context)); --hash_value列用来存储context列的MD5散列值
mysql> insert into t values(2,repeat('beijing',2),md5(context));
mysql> insert into t values(3,repeat('beijing 2008',2),md5(context));
mysql> select * from t;
mysql> select * from t where hash_value=md5(repeat('beijing 2008',2));--通过id=3的md5散列值来查询

--前缀索引:对 BLOB 或者 CLOB 字段进行模糊查询


mysql> create index idx_blob on t(context(100)); --只为字段的前 n 列创建索引


mysql> desc select * from t where context like 'beijing%' \G;

--注意:这里的查询条件中,“%”不能放在最前面,否则索引将不会被使用


1.在不必要的时候避免检索大型的 BLOB 或 TEXT 值;慎用select * ;


2.把 BLOB 或 TEXT 列分离到单独的表中;减少主表中的碎片,可以得到固定长度数据行的性能优势。


它还可以使主数据表在运行 SELECT * 查询的时候不会通过网络传输大量的 BLOB 或 TEXT 值。


--3.浮点数与定点数


在 MySQL 中 float、double(或 real)用来表示浮点数。


在 MySQL 中,decimal (或 numberic)用来表示定点数。


定点数实际上是以字符串形式存放的,所以定点数可以更加精确的保存数据.


--浮点数与定点数的区别


mysql> CREATE TABLE test (c1 float(10,2),c2 decimal(10,2));
mysql> insert into test values(131072.32,131072.32);
mysql> select * from test;
+-----------+-----------+
| c1 | c2 |
+-----------+-----------+
| 131072.31 | 131072.32 |
+-----------+-----------+
1 row in set (0.00 sec)2

--浮点数的比较也是一个普遍存在的问题


public class Test{
public static void main(String[] args) throws Exception{
System.out.println("7.22-7.0 = " + (7.22f-7.0f));
}
}
Result: 7.22-7.0 = 0.21999979


所以在编程中应尽量避免浮点数的比较,如果非要使用浮点数比较则最好使用范围比较而不要使用“==”比较


--注意: 在今后关于浮点数和定点数的应用中,用户要考虑到以下几个原则:


 1.浮点数存在误差问题;


 2.对货币等对精度敏感的数据,应该用定点数表示或存储;


 3.在编程中,如果用到浮点数,要特别注意误差问题,并尽量避免做浮点数比较;


 4.要注意浮点数中一些特殊值的处理。


--提供浮点数精确运算的算法:


import java.math.BigDecimal;
/**
*support exact arithmetic
*@param v1
*@param v2
*/
public class Test{
public static void main(String[] args) throws Exception{
System.out.print("7.22-7.0=" + subtract(7.22,7.0));
}
public static double subtract(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
}


--4.日期类型选择


1.根据实际需要选择能够满足应用的最小存储的日期类型。如果应用只需要记录“年


份”,那么用 1 个字节来存储的 YEAR 类型完全可以满足,而不需要用 4 个字节来


存储的 DATE 类型。这样不仅仅能节约存储,更能够提高表的操作效率。


2.如果要记录年月日时分秒,并且记录的年份比较久远,那么最好使用 DATETIME,


而不要使用 TIMESTAMP。因为 TIMESTAMP 表示的日期范围比 DATETIME 要短得多。


3.如果记录的日期需要让不同时区的用户使用,那么最好使用 TIMESTAMP,因为日


期类型中只有它能够和实际时区相对应。


-------------------------------字符集-------------------------------


--1.字符集概述


ASCII:American Standard Code for Information Interchange -> ISO-646

--2.Unicode 简述


Unicode:双字节编码


Unicode 2.0等同于ISO/IEC 10646-1:1993。


 Unicode 3.0等同于ISO/IEC 10646-1:2000。


 Unicode 4.0等同于ISO/IEC 10646:2003。


--3.汉字及一些常见字符集


GB2312-80、GB13000、GBK、GB18030


常用字符集比较


-- 字符集 是否定长 编码方式 其他说明


ACSII 是 单字节 7 位编码 最早的奠基性字符集


ISO-8859-1/latin1 是 单字节 8 位编码 西欧字符集,经常被一些程序员用来转码


GB2312-80 是 双字节编码 早期标准,不推荐再使用


GBK 是 双字节编码 虽然不是国标,但支持的系统不少


GB18030 否 2 字节或 4 字节编码 开始有一些支持,但数据库支持的还少见


UTF-32 是 4 字节编码 UCS-4 原始编码,目前很少采用


UCS-2 是 2 字节编码 Windows 2000 内部用 UCS-2


UTF-16 否 2 字节或 4 字节编码 Java 和 Windows XP/NT 等内部使用 UTF-16


UTF-8 否 1 至 4 字节编码 互联网和 UNIX/Linux 广泛支持的 Unicode 字符集;MySQLServer 也使用 UTF-8


--4.怎样选择合适的字符集


(1)满足应用支持语言的需求,如果应用要处理各种各样的文字,或者将发布到使用不同语言的国家或地区,


就应该选择 Unicode 字符集。对 MySQL 来说,目前就是 UTF-8。


(2)如果应用中涉及已有数据的导入,就要充分考虑数据库字符集对已有数据的兼容性。


假如已有数据是 GBK 文字,如果选择 GB2312-80 为数据库字符集,就很可能出现某些文字无法正确导入的问题。


(3)如果数据库只需要支持一般中文,数据量很大,性能要求也很高,那就应该选择


双字节定长编码的中文字符集,比如 GBK。因为,相对于 UTF-8 而言,GBK 比较“小”,


每个汉字只占2个字节,而UTF-8汉字编码需要3个字节,这样可以减少磁盘I/O、数据库cache,


以及网络传输的时间,从而提高性能。相反,如果应用主要处理英文字符,仅有少量汉字数


据,那么选择 UTF-8 更好,因为 GBK、UCS-2、UTF-16 的西文字符编码都是 2 个字节,会造成很大不必要的开销。


(4)如果数据库需要做大量的字符运算,如比较、排序等,选择定长字符集可能更好,


因为定长字符集的处理速度要比变长字符集的处理速度快。


(5)如果所有客户端程序都支持相同的字符集,应该优先选择该字符集作为数据库字


符集。这样可以避免因字符集转换带来的性能开销和数据损失。


--5.MySQL 支持的字符集简介


MySQL 服务器可以支持多种字符集,在同一台服务器、同一个数据库、甚至同一个表


的不同字段都可以指定使用不同的字符集,相比 Oracle 等其他数据库管理系统,在同一个


数据库只能使用相同的字符集,MySQL 明显存在更大的灵活性。


查看所有可用的字符集:show character set;


显示所有的字符集和该字符集默认的校对规则:desc information_schema.character_sets;


每个字符集至少对应一个校对规则。可以用“SHOW COLLATION LIKE '***';


”命令或者查看 information_schema.COLLATIONS;SHOW COLLATION LIKE 'gbk%';


--6.MySQL 字符集的设置


MySQL 的字符集和校对规则有 4 个级别的默认设置:


服务器级、


数据库级、


表级和字


段级。


它们分别在不同的地方设置,作用也不相同。


1.服务器字符集和校对规则


查询当前服务器的字符集:show variables like 'character_set_server';


查询当前服务器的校对规则:show variables like 'collation_server';


2.数据库字符集和校对规则


设置数据库字符集的规则是:


 1) 如果指定了字符集和校对规则,则使用指定的字符集和校对规则;


 2)如果指定了字符集没有指定校对规则,则使用指定字符集的默认校对规则;


 3)如果没有指定字符集和校对规则,则使用服务器字符集和校对规则作为数据库的字符集和校对规则。


3.表字符集和校对规则


设置表的字符集的规则和上面基本类似;


推荐在创建表的时候明确指定字符集和校对规则,避免受到默认值的影响。


显示表的字符集和校对规则:show create table t_book \G;


4.列字符集和校对规则


一般遇到这种情况的几率比较小,这只是 MySQL 提供给我们一个灵活设置的手段。


5.连接字符集和校对规则


客户端和服务器之间交互的字符集和校对规则的设置


通常情况下,基本不需要用户强制指定字符串字符集。


--7.字符集的修改步骤


字符集的修改不能直接通过“alter database character set ***”或者“alter table tablename character set ***”


命令进行,这两个命令都没有更新已有记录的字符集,而只是对新创建的表或者记录生效。


已有记录的字符集调整,需要先将数据导出,经过适当的调整重新导入后才可完成。


-- 模拟的是将 latin1 字符集的数据库修改成 GBK 字符集的数据库的过程


(1)导出表结构:

mysqldump -uroot -p --default-character-set=gbk -d databasename> createtab.sql


--default-character-set=gbk 表示设置以什么字符集连接,


-d 表示只导出表结构,不导出数据。


(2)手工修改 createtab.sql 中表结构定义中的字符集为新的字符集。


(3)确保记录不再更新,导出所有记录。


mysqldump -uroot -p --quick --no-create-info --extended-insert
--default-character-set=latin1 databasename> data.sql
--quick:该选项用于转储大的表。


它强制 mysqldump 从服务器一次一行地检索表中的行而不是检索所有行,并在输出前将它缓存到内存中。


--extended-insert:使用包括几个 VALUES 列表的多行 INSERT 语法。这样使转储文件更小,重载文件时可以加速插入。


--no-create-info:不写重新创建每个转储表的 CREATE TABLE 语句。


--default-character-set=latin1:按照原有的字符集导出所有数据,这样导出的文件中,


所有中文都是可见的,不会保存成乱码。


(4)打开 data.sql,将 SET NAMES latin1 修改成 SET NAMES gbk。


(5)使用新的字符集创建新的数据库。

create database databasename default charset gbk;


(6)创建表,执行 createtab.sql。

mysql -uroot -p databasename < createtab.sql


(7)导入数据,执行 data.sql。

mysql -uroot -p databasename < data.sql


本文由职坐标整理并发布,了解更多内容,请关注职坐标MySQL数据库频道!


本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程