Mysql表设计需要注意的问题

Wesley13
• 阅读 682

下面探讨的数据库为MySQL 存储引擎为innodb因为这是最常见的,使用最多的数据库和引擎

什么是页分裂?
这是因为聚簇索引采用的是平衡二叉树算法,而且每个节点都保存了该主键所对应行的数据,假设插入数据的主键是自增长的,那么根据二叉树算法会很快的把该数据添加到某个节点下,而其他的节点不用动;但是如果插入的是不规则的数据,那么每次插入都会改变二叉树之前的数据状态。从而导致了页分裂。

为什么一定要设置一个主键
因为就算你不主动设置一个主键,innodb也会帮你生成一个隐藏列,作为自增主键来使用。所以,不管怎么样都会有自增主键,还不如自己指定一个,主键索引可以提高查询效率。

主键使用自增还是UUID
主键肯定是用自增。innodb种的主键是聚族索引,如果主键是自增的,那么每次插入的新数据都会顺序添加到当前索引节点的后续位置,当一页写满时,就会自动开启第二页,如果不是自增主键,那么就可能在中间插入,就会引发页的分裂,产生很多碎片,总之用自增主键性能更好。

UUID产生的索引文件更大,当数据量超过一百万行时,主键查询性能和索引文件大小都比UUID要更有效率和更小。

主键为什么不推荐有业务含义

1)因为任何含有业务的列都有改变的可能性,主键一旦带上业务含义,那么主键就有可能发生改变。主键发生改变,该数据在磁盘上的存储位置就会发生更改,有可能引发页分裂,产生空间碎片。

2)带有业务含义的主键不一定是顺序自增的,就有可能导致后边插入的数据主键一定比前面的大,如果出现后边插入的数据主键比前面插入的小,就肯能引发页分裂,产生空间碎片。  

表示枚举的字段为什么不用enum类型
首先,枚举在MySQL中一般用tinyint类型,为什么不使用enum呢

1)ENUM类型,order by操作效率低,需要额外的操作

2)如果枚举是数值,有陷阱

例如:表结构如下create table test(sex enum('0','1'))此时执行插入语句insert into test values(1) 查询的结果为0

只有这样插入insert into test values('1')此时结果才是1

货币字段用什么类型
货币:如果货币单位是分,可以使用int类型,如果坚持用元的话,可以使用Decimal类型,不能使用float和double类型,因为这两个类型是以二进制存储的,所有有一定的误差。

例如:create table 't'('price' float(10,2) default null) engine=innodb default charset=utf8然后插入一条数据price=120.23,然后你会发现数据变为120.25,精度失准。

时间字段用什么类型
1)如果使用varchar,优点是显示直观,缺点是做时间比较运算的时候,需要使用str_to_date等函数把它转化为事件类型,你会发现这是无法命中索引的,数据量一大,这就是一个大坑。

2)如果使用timestamp类型,该类型为4个字节,表示的时间范围为1970-01-01 到2038-01-19 也就是说2038年以后的时间不能使用timestamp存储。该类型有一个优势,就是自带时区,如果修改了时区,该字段值会跟着改变。

3)dtatime类型,该类型为8个字节,自己维护一个时间戳,表示范围比timestamp大,因为需要自己维护,所以不太方便。

为什么不直接存储图片、音频、视频等大容量内容
在实际生产中,我们都是在文件服务器上存真实文件,数据库中保存对应的文件路劲即可,MySQL有存放大文件的类型,text和blob类型,但是基本不使用

1)MySQL内存临时表不支持text、blob这样的大数据类型,如果查询中包含这样的数据,在排序等操作时,就不能使用内存临时表,必须使用磁盘临时表,导致效率低下。

2)binlog内容太多,因为数据内容过大,会导致binlog内容较多,而MySQL主从同步靠binlog进行同步,binlog太大就会导致主从同步效率问题。

字段为什么要定义为NOT NULL
1)索引性能不好

2)查询会出现一些不可预料的结果

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这