Mysql基本数据类型

Schema与数据类型优化

1选择优化的数据类型

1.1更小的通常更好

选择你认为不会超过范围的最小类型

1.2简单就好

整型比字符操作代价更低,因为字符型的校对规则比整型比较更复杂,一个是使用mysql内建的类型而不是字符串存储日期和时间,另外一个是使用整型存储IP地址

1.3尽量避免NULL

可为NULL的列使得索引、索引统计、和值比较更为复杂。可为NULL的列会使用更多的存储空间,在MYsql例也需要特俗存储

总结:

在为列选择数据类型时,第一步需要确定合适大类型,数字、字符串、时间,这通常标胶简单

2、整数类型

整数

TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT 8,16,24,32,64

整数类型为TINYINT UNSIgned,表示不允许为负值,这使得正数的上限提升一倍,有符号和无符号,使用相同的存储空间,具有相同的性能

实数

FLOAT DOUBLE DECIMAL,浮点类型在存储同样范围值的时候,通常比DECIMAL使用更少的空间

因此需要额外的空间和时间开销,因此尽量只在对小数进行精确计算时,才使用DECIMAL,但在数据量较大时,应当使用BIGINT,将小数乘以一百万,,可以同时避免浮点存储计算

字符串类型

VARCHAR

存储可变长字符串,比定长字符串更节省空间,VARCHAR需要1-2字节记录字符串的长度,VARCHAR节省了存储空间,对性能有帮助,但是由于行是变长的,所以update时,可能使行变得比原来更长,下列情况使用VARCHAR是合适的,字符串列的最大长度比平均长度大很多,列的更新很少,所以碎片不是问题。

CHAR

MYSQL总是根据分配的字符串长度分配足够的空间,当存储为char时,会删除所有的末尾空格,CHAR适合存储所有很短的字符串,或者所有的字符串都接近一个长度。

BLOB、TEXT

二者都是为了存储很大的数据而设计的字符串的数据类型,分别使用二进制和字符方式存储,

不同的是,BLOB二进制没有排序规则,TEXT有字符集和排序规则,再进行排序时,只能对该字段的最前面的部分字符进行排序

使用枚举代替字符串类型

目前没遇到,不进行学习

日期和时间类型

DATETIME

这个类型保存大范围的值,从1001到9999年,日期和时间封装到格式为YYYYMMDDHHMMSS,与时区无关,使用8个字节的存储空间

TIMESTAMP

1970倒2038年,日期和时间封装到格式为YYYYMMDDHHMMSS,与时区有关,使用4个字节的存储空间,对于TIMESTAMP,它把客户端插入的时间从当前时区转化为UTC(世界标准时间)进行存储。查询时,将其又转化为客户端当前时区进行返回。而对于DATETIME,不做任何改变,基本上是原样输入和输出。

关于TIMESTAMP和DATETIME的自动初始化和更新

自动初始化指的是如果对该字段(譬如上例中的hiredate字段)没有显性赋值,则自动设置为当前系统时间。

自动更新指的是如果修改了其它字段,则该字段的值将自动更新为当前系统时间。

范式是符合某一种级别的关系模式的集合。构造数据库必须遵循一定的规则。在关系数据库中,这种规则就是范式。

关系数据库中的关系必须满足一定的要求,即满足不同的范式。大数据生态中,各类强大的查询引擎层出不穷,相对廉价的磁盘和分布式技术,也让数据冗余变得可接受甚至更加方便。

在创建一个数据库的过程中,范化是将其转化为一些表的过程,这种方法可以使从数据库得到的结果更加明确。这样可能使数据库产生重复数据,从而导致创建多余的表。范化是在识别数据库中的数据元素、关系以及定义所需的表和各表中的项目等这些初始工作之后的一个细化的过程。

范式和反范式

1. 第一范式
1NF是对属性的原子性,要求属性具有原子性,即列不可再分解;

如学生(学号,姓名,性别,出生年月日)

2. 第二范式
2NF是对记录的惟一性,要求记录有惟一标识,即实体的惟一性,即不存在部分依赖;
简单来说就是拆表,以人为粒度做一张明细表,以课程号为粒度做一张维度表,两表关联使用,消除了数据冗余

表:学号、课程号、姓名、学分;

这个表明显说明了两个事务:学生信息, 课程信息;由于非主键字段必须依赖主键,这里学分依赖课程号,姓名依赖与学号,所以不符合二范式。

可能会存在问题:

数据冗余:每条记录都含有相同信息;

删除异常:删除所有学生成绩,就把课程信息全删除了;

插入异常:学生未选课,无法记录进数据库;

更新异常:调整课程学分,所有行都调整。

正确做法:

学生:Student(学号, 姓名);

课程:Course(课程号, 学分);

选课关系:StudentCourse(学号, 课程号, 成绩)。

三、第三范式

3NF是对字段的冗余性,要求任何字段不能由其他字段派生出来,它要求字段没有冗余,即不存在传递依赖;

表: 学号, 姓名, 年龄, 学院名称, 学院电话

因为存在依赖传递: (学号) → (学生)→(所在学院) → (学院电话) 。

可能会存在问题:

数据冗余:有重复值;

更新异常:有重复的冗余信息,修改时需要同时修改多条记录,否则会出现数据不一致的情况 。

正确做法:

学生:(学号, 姓名, 年龄, 所在学院);

学院:(学院, 电话)。

范式的优缺点和反范式的优缺点

查询记录时,范式模式往往要进行多表连接,而反范式只需在同一张表中查询,当数据量很大的时候,显然反范式的效率会更好。
反范式有很多重复的数据,会占用更多的内存,查询时可能会较多地使用DROUP BY或DISTINCT等耗时耗性能的关键字。
当要修改更新数据时(例如修改Accounting部门的领导为Russell),范式更灵活,而反范式要修改全部的数据,且易出错。

混用范式化和反范式化是一个常用的技巧

加快更改表结构的速度

MySql的ALTER TABLE 操作的性能对大表来说是个大问题。MySQL执行大部分修改表结构操作的方法是用新的结构创建一个空表,从旧表中查出所有数据插入新表,然后删除旧表。这样操作肯呢个需要花费很长时间,如果内存不足而表又很大,而且还有很多索引的情况下尤其如此。许多人都有这样的经验。ALTER TABLE操作需要花费数个小时甚至数天才能完成。

一般而言,大部分ALTER TABLE操作将导致MySQL服务中断。我们会展示一些在DDL操作时使用的技巧,但这是针对一些特殊场景而言的。对常见的场景,能使用的技巧只有两种:一种是先在一台不提供服务的机器上执行ALTER TABLE操作,然后和提供服务的主库进行切换;另外一种技巧是“影子拷贝”。影子拷贝的技巧是用要求的表结构创建一张和源表无关的新表,然后通过重命名和删表操作交换两张表。

不是所有的ALTER TABLE操作都会引起表重建。例如,有两种方法可以改变或者删除一个列的默认值(一种方法很快,另外一种则很慢)。假如要修改电影的默认租赁期限,从三天到五天。下面是很慢的方式:

mysql> ALTER TABLE sakila.film

         ->MODIFY COLUMN rental_duration TINYINT(3)  NOT NULL DEFAULT 5;

SHOW STATUS 显示这个语句做了1000次读和1000次插入操作。换句话说,它拷贝了整张表到一张新表,甚至列的类型,大小和可否为NULL属性都没改变。

理论上,MySQL可以跳过创建新表的步骤。列的默认值实际上存在表的.frm文件中,所以可以直接修改这个文件而不需要改动表本身。然而MySQL还没有采用这种优化的方法,所有的MODIFY COLUMN操作都将导致表重建。

另外一种方法是通过ALTER COLUMN操作来改变列的默认值:

mysql>ALTER TABLE sakila.film

         ->ALTER COLUMN rental_duration SET DEFAULT 5;

这个语句会直接修改.frm文件而不涉及表数据。所以,这个操作是非常快的。