MySQL优化(1):字段的设计
web项目中,当java或者go等语言速度提升到瓶颈的时候,我们需要关心mysql的优化
可以优化的方面有很多:设计表、负载均衡、读写分离、sql语句优化等
(1)ip地址设计
例如我们需要存储ip地址:192.168.1.1
第一反应是选用varchar(15);但是更好的方式是int unsigned(占用四个字节)
因为:ip地址可以很容易地转换为无符号整数
仔细观察ip地址,四部分都是0-255的数字,1个字节(8位)恰好可以表示0-255的整数
而mysql有函数:inet_aton():地址转成数字,inet_ntoa():数字转成地址
示例:
select inet_aton('192.168.0.1')
结果:3232235521
select inet_ntoa("3232235521")
结果:192.168.0.1
int unsigned占用字节少于varchar(15),并且整数查询效率更高(代价是需要使用转换函数)
总结:在设计字段的时候,尽量使用整数来表示字符串
(2)关联表设计
整型的优势:固定存储空间,通常是少量空间
例如:mysql内部的枚举和集合类型:
enum(男,女,未知)
insert into user(gender) values(男)
这句话在mysql中实际存储的是1,这就是最典型的把字符串存成整数
注意:实际中,很少使用mysql的enum和set,因为维护成果过高
比如性别需要把未知改为人妖,需要执行alter table modify column操作,需要独占整张表,检查记录性别值的合法性
如果一定要使用这种方式:关联表,字段id,title,存储1,男,2,女。这种方式使用较为广泛
但是,比如家庭地址这样的字符串,是无法改成整型的,不能强行操作
(3)金额存储
金额的存储对数据的精度要求较高,按理来说要使用decimal()
例如decimal(10,2):有2位小数的定点数
实际中有另一种操作:int或bigint,这时候为了精度不丢失,采用”分“为单位(12.51元记录为1251)
计算机中小数是无法做到不损失精度的,但是金额较特殊,固定了两位小数,所以可以采用这种方式
而且编程中,整数的计算相对于小数较为方便
decimal也有擅长的地方,比如存储大数:123456789123456789
这时候不可以使用int,只能使用bigint或者decimal
注意:这里为什么我们不选择浮点数double和float呢?因为浮点数会导致精度丢失
原因:浮点数占用固定的存储空间,无论存储多大的数,空间是一定的;但是定点数空间会随着数字变大而增加
由此引出了定长类型和变长类型:
定长类型:存储空间固定(int、float、double、char、date、time、datetime、year、timestamp)
变长类型:存储空间可变(varchar、decimal、text)
注意:只有定长类型才会有损失精度的问题,定长类型效率较高
结论:在乎存储空间采用定长类型,在乎存储精度采用变长类型
(4)text和varchar的选择
text:通常感觉存储容量较大,其实最大容量和varchar的最大容量几乎一样
但是,text是独立存储的,不占用字段的总空间,但是varchar占用字段总空间,通常总空间是65535字节
结论:更大的数据还是采用text更好
更大的数据类型有longtext,可以用于选择
(5)字段设计的原则
1.尽可能选择小的数据类型,这条无需多说
2.尽可能使用not null,因为数据库不需要判断是否为null,null在mysql中的存储和运算更麻烦:
null参与常规运算的结果都是null,当判断是否为空的时候,必须采用is null和is not null
mysql中每条记录会使用到额外的存储空间,用于表示每个字段是否为null
通常使用一个特殊的数据来占位,比如我要表达null通常设置为空字符串或者0
这种情况又会出现问题,比如成绩字段,0代表没有的话无法区分0分的学生,所以可以采用-1,消除歧义
3.字段注释要完整:gender int comment '性别'
4.单张表的字段数量不宜过多,通常最多二三十个;数量过多通常会出现某个业务逻辑只是用其中一部分,浪费性能
5.预留字段,比如field1 int field2 varcahr等等;后期项目如果需要更改表结构,这样做会方便很多
(6)关联表的设计
一对一:一条记录的字段较多,分布到多个表中存储
例如学生表,基础信息:姓名、身高、班级,还有一些不常用的数据:籍贯、家庭成员等信息
这时候应该设计基础信息一张表,不常用数据一张表,使用相同的主键来表示
一对多:在多的一端使用关联字段,关联一端的主键
例如文章和分类表,分类是一端,文章是多端;那么在文章表中需要有一个分类id的字段做关联
多对多:使用中间表来实现
例如文章和标签,多对多,那么就需要一张表,字段至少有id、文章id、标签id,每一条记录代表一个关联
(7)范式
第一范式:字段的原子性,不可再分割
关系型数据库默认满足第一范式,mysql满足
但也可以强行做:比如一个时间字段,同时写入开始时间和结束时间,这就不合理
一个容易出现的问题:(6)中的例子,文档和标签的设计中:如果我为了省事,不引入第三张表,而是在文章表中用一个字段标签ids字段(例如存入1,2,3)
这种情况很常见,是不合理的做法,在更新的时候会出现很多问题,需要把逗号拆开处理,而且无法建索引
除非是类似日志系统,存入后不再维护,那么可以使用这种方式
第二范式:满足第一范式后,消除对主键的部分依赖(a字段可以确定b字段,那么b字段依赖a字段)
主键:可以唯一标识记录的字段或者字段集合
部分依赖:如果某个字段依赖复合主键的一部分字段,称之为对主键的部分依赖
例如一个课程信息表,字段有:老师,性别,班级,教室,时间,但是不存在id
这时候需要我们选一个主键,这里面每一个字段都不能作为主键
老师和班级同时可以作为一个主键(复合主键)
但是性别对主键是部分依赖,如何消除呢?
部分依赖的产生必须是复合主键,那么增加一个id即可消除对主键的部分依赖
第三范式:第二范式的基础上,消除对主键的传递依赖
传递依赖:c依赖于b,b依赖于主键,那么c对主键存在传递依赖关系
上门的例子:性别依赖于老师,老师依赖于id,那么存在传递依赖关系
消除方式:将独立数据单独建表,使用关联字段进行存储
例子中,建立一个单独的表,记录老师和性别的关系
总结:独立数据独立建表;表中存在与业务逻辑无关的id主键;表之间的关系由关联字段(或关联表)进行表示
通俗来讲:我们建表中,基本都是满足三大范式的
上一篇: Java继承与多态的正确打开方式
下一篇: 详细聊聊JDK中的反模式接口常量
推荐阅读
-
一个简单的PHP&MYSQL留言板源码第1/2页
-
MySQL中聚合函数count的使用和性能优化技巧
-
提高MySQL 查询效率的三个技巧第1/2页
-
Mysql优化order by语句的方法详解
-
Mysql数据库实现多字段过滤的方法
-
mysql下创建字段并设置主键的php代码
-
[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause 的问题 MySQL
-
Mysql字符串字段判断是否包含某个字符串的方法(代码)
-
ASP.NET页面进行GZIP压缩优化的几款压缩模块的使用简介及应用测试!(附源码)第1/2页
-
VI设计网:思维培养是成为SEO优化高手的捷径