mysql创建表字段不定_mysql怎么选择合适的字段创建表在设计表的时候,⽐如姓名 有可能是2个字 3个 或者4个等那么是设置字段属性是char还是varchar呢 是设置定长合理还是变长呢?
很多⼈都将作为数据库表结构设计“圣经”,认为只要按照这个范式需求设计,就能让设计出来的表结构⾜够优化,既能保证性能优异同时还能满⾜扩展性要求。殊不知,在N年前被奉为“圣经”的数据库设计3范式早就已经不完全适⽤了。这⾥我整理了⼀些⽐较常见的数据库表结构设计⽅⾯的优化技巧,希望对⼤家有⽤。
由于MySQL数据库是基于⾏(Row)存储的数据库,⽽数据库操作 IO 的时候是以 page(block)的⽅式,也就是说,如果我们每条记录所占⽤的空间量减⼩,就会使每个page中可存放的数据⾏数增⼤,那么每次 IO 可访问的⾏数也就增多了。反过来说,处理相同⾏数的数据,需要访问的 page 就会减少,也就是 IO 操作次数降低,直接提升性能。此外,由于我们的内存是有限的,增加每个page中存放的数据⾏数,就等于增加每个内存块的缓存数据量,同时还会提升内存换中数据命中的⼏率,也就是缓存命中率。
enum怎么用数据类型选择
数据库操作中最为耗时的操作就是 IO 处理,⼤部分数据库操作 90% 以上的时间都花在了 IO 读写上⾯。所以尽可能减少 IO 读写量,可以在很⼤程度上提⾼数据库操作的性能。
我们⽆法改变数据库中需要存储的数据,但是我们可以在这些数据的存储⽅式⽅⾯花⼀些⼼思。下⾯的这些关于字段类型的优化建议主要适⽤于记录条数较多,数据量较⼤的场景,因为精细化的数据类型设置可能带来维护成本的提⾼,过度优化也可能会带来其他的问题:
1.数字类型:⾮万不得已不要使⽤DOUBLE,不仅仅只是存储长度的问题,同时还会存在精确性的问题。同样,固定精度的⼩数,也不建议使⽤DECIMAL,建议乘以固定倍数转换成整数存储,可以⼤⼤节省存储空间,且不会带来任何附加维护成本。对于整数的存储,在数据量较⼤的情况下,建议区分开 TINYINT / INT / BIGINT 的选择,因为三者所占⽤的存储空间也有很⼤的差别,能确定不会使⽤负数的字段,建议添加unsigned定义。当然,如果数据量较⼩的数据库,也可以不⽤严格区分三个整数类型。
2.字符类型:⾮万不得已不要使⽤ TEXT 数据类型,其处理⽅式决定了他的性能要低于char或者是varchar类型的处理。定长字段,建议使⽤ CHAR 类型,不定长字段尽量使⽤ VARCHAR,且仅仅设定适当的最⼤长度,⽽不是⾮常随意的给⼀个很⼤的最⼤长度限定,因为不同的长度范围,MySQL也会有不⼀样的存储处理。
3.时间类型:尽量使⽤TIMESTAMP类型,因为其存储空间只需要 DATETIME 类型的⼀半。对于只需要精确到某⼀天的数据类型,建议使⽤DATE类型,因为他的存储空间只需要3个字节,⽐TIMESTAMP还少。不建议通过INT类型类存储⼀个unix timestamp 的值,因为这太不直观,会给维护带来不必要的⿇烦,同时还不会带来任何好处。
4.ENUM & SET:对于状态字段,可以尝试使⽤ ENUM 来存放,因为可以极⼤的降低存储空间,⽽且即使需要增加新的类型,只要增加于末尾,修改结构也不需要重建表数据。如果是存放可预先定义的属性数据呢?可以尝试使⽤SET类型,即使存在多种属性,同样可以游刃有余,同时还可以节省不⼩的存储空间。
5.LOB类型:强烈反对在数据库中存放 LOB 类型数据,虽然数据库提供了这样的功能,但这不是他所擅长的,我们更应该让合适的⼯具做他擅长的事情,才能将其发挥到极致。在数据库中存储 LOB 数据就像让⼀个多年前在学校学过⼀点Java的营销专业⼈员来写 Java 代码⼀样。
字符编码
字符集直接决定了数据在MySQL中的存储编码⽅式,由于同样的内容使⽤不同字符集表⽰所占⽤的空间⼤⼩会有较⼤的差异,所以通过使⽤合适的字符集,可以帮助我们尽可能减少数据量,进⽽减少IO操作次数。
1.纯拉丁字符能表⽰的内容,没必要选择 latin1 之外的其他字符编码,因为这会节省⼤量的存储空间。
2.如果我们可以确定不需要存放多种语⾔,就没必要⾮得使⽤UTF8或者其他UNICODE字符类型,这回造成⼤量的存储空间浪费。
3.MySQL的数据类型可以精确到字段,所以当我们需要⼤型数据库中存放多字节数据的时候,可以通过对不同表不同字段使⽤不同的数据类型来较⼤程度减⼩数据存储量,进⽽降低 IO 操作次数并提⾼缓存命中率。
适当拆分
有些时候,我们可能会希望将⼀个完整的对象对应于⼀张数据库表,这对于应⽤程序开发来说是很有好的,但是有些时候可能会在性能上带来较⼤的问题。
当我们的表中存在类似于 TEXT 或者是很⼤的 VARCHAR类型的⼤字段的时候,如果我们⼤部分访问这张表的时候都不需要这个字段,我们就该义⽆反顾的将其拆分到另外的独⽴表中,以减少常⽤数据所占⽤的存储空间。这样做的⼀个明显好处就是每个数据块中可以存储的数据条数可以⼤⼤增加,既减少物理 IO 次数,也能⼤⼤提⾼内存中的缓存命中率。
上⾯⼏点的优化都是为了减少每条记录的存储空间⼤⼩,让每个数据库中能够存储更多的记录条数,以达到减少 IO 操作次数,提⾼缓存命中率。下⾯这个优化建议可能很多开发⼈员都会觉得不太理解,因为这是典型的反范式设计,⽽且也和上⾯的⼏点优化建议的⽬标相违背。
适度冗余
为什么我们要冗余?这不是增加了每条数据的⼤⼩,减少了每个数据块可存放记录条数吗?
确实,这样做是会增⼤每条记录的⼤⼩,降低每条记录中可存放数据的条数,但是在有些场景下我们仍然还是不得不这样做:
1.被频繁引⽤且只能通过 Join 2张(或者更多)⼤表的⽅式才能得到的独⽴⼩字段。
2.这样的场景由于每次Join仅仅只是为了取得某个⼩字段的值,Join到的记录⼜⼤,会造成⼤量不必要的 IO,完全可以通过空间换取时间的⽅式来优化。不过,冗余的同时需要确保数据的⼀致性不会遭到破坏,确保更新的同时冗余字段也被更新。
尽量使⽤ NOT NULL
NULL 类型⽐较特殊,SQL 难优化。虽然 MySQL NULL类型和 Oracle 的NULL 有差异,会进⼊索引中,但如果是⼀个组合索引,那么这个NULL 类型的字段会极⼤影响整个索引的效率。此外,NULL 在索引中的处理也是特殊的,也会占⽤额外的存放空间。
很多⼈觉得 NULL 会节省⼀些空间,所以尽量让NULL来达到节省IO的⽬的,但是⼤部分时候这会适得其反,虽然空间上可能确实有⼀定节省,倒是带来了很多其他的优化问题,不但没有将IO量省下来,反⽽加⼤了SQL的IO量。所以尽量确保 DEFAULT 值不是 NULL,也是⼀个很好的表结构设计优化习惯。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论