Mysql的建表规范与注意事项

  1. 库名、表名、字段名必须使用小写字母,“_”分割。
  2. 库名、表名、字段名必须不超过12个字符。
  3. 库名、表名、字段名见名知意,建议使用名词而不是动词。



一、建议使用InnoDB存储引擎。
               存储引擎:innoDb支持事物,myisam不支持事物,建议使用innoDb, 5.5以后的默认引擘,支持事务,行级锁,更好的恢复性,高并发下性能更好,对多核,大内存,ssd等硬件支持更好。
      (1)    
             MyISAM表是独立于操作系统的,这说明可以轻松地将其从Windows服务器移植到Linux服务器;每当我们建立一个MyISAM引擎的表时,就会在本地磁盘上建立三个文件,文件名就是表明。例如,我建立了一个MyISAM引擎的tb_Demo表,那么就会生成以下三个文件:

1.tb_demo.frm,存储表定义;
2.tb_demo.MYD,存储数据;
3.tb_demo.MYI,存储索引。

MyISAM表无法处理事务,这就意味着有事务处理需求的表,不能使用MyISAM存储引擎。MyISAM存储引擎特别适合在以下几种情况下使用:
1.选择密集型的表。MyISAM存储引擎在筛选大量数据时非常迅速,这是它最突出的优点。
2.插入密集型的表。MyISAM的并发插入特性允许同时选择和插入数据。例如:MyISAM存储引擎很适合管理邮件或Web服务器日志数据。
(2)        
            InnoDB是一个健壮的事务型存储引擎,这种存储引擎已经被很多互联网公司使用,为用户操作非常大的数据存储提供了一个强大的解决方案。我的电脑上安装的MySQL 5.6.13版,InnoDB就是作为默认的存储引擎。InnoDB还引入了行级锁定和外键约束,在以下场合下,使用InnoDB是最理想的选择:

1.更新密集的表。InnoDB存储引擎特别适合处理多重并发的更新请求。
2.事务。InnoDB存储引擎是支持事务的标准MySQL存储引擎。
3.自动灾难恢复。与其它存储引擎不同,InnoDB表能够自动从灾难中恢复。
4.外键约束。MySQL支持外键的存储引擎只有InnoDB。
5.支持自动增加列AUTO_INCREMENT属性。

一般来说,如果需要事务支持,并且有较高的并发读取频率,InnoDB是不错的选择。

(3):不经常使用
       (1)、  MEMORY   :使用MySQL Memory存储引擎的出发点是速度
            1.目标数据较小,而且被非常频繁地访问。在内存中存放数据,所以会造成内存的使用,可以通过参数max_heap_table_size控制Memory表的大小,设置此参数,就可以限制Memory表的最大大小。
             2.如果数据是临时的,而且要求必须立即可用,那么就可以存放在内存表中。
             3.存储在Memory表中的数据如果突然丢失,不会对应用服务产生实质的负面影响。
        (2)、    MERGE
               MERGE存储引擎是一组MyISAM表的组合,这些MyISAM表结构必须完全相同,尽管其使用不如其它引擎突出,但是在某些情况下非常有用。说白了,Merge表就是几个相同MyISAM表的聚合器;Merge表中并没有数据,对Merge类型的表可以进行查询、更新、删除操作,这些操作实际上是对内部的MyISAM表进行操作。Merge存储引擎的使用场景
          


二、存储精确浮点数必须使用DECIMAL替代FLOAT和DOUBLE。
           (1) decimal 类型可以精确地表示非常大或非常精确的小数。大至 1028(正或负)以及有效位数多达 28 位的数字可以作为 decimal类型存储而不失其精确性。该类型对于必须避免舍入错误的应用程序(如记账)很有用。
1、   decimal   类型是适合财务和货币计算的   128   位数据类型。
2、   decimal不是浮点型、decimal不存在精度损失;
3、   decimal所能储存的数比double大,从double到decimal的类型转换不会出现任何问题。
4、   
float 单精度浮点 32bit,
double 双精度浮点64bit,
decimal是高精度 128bit,浮点型。
float double 是 基本类型(primitive type),decimal不是
5、  浮点数运算会有精度损失问题,有精度损失时程序不会报告,要程序员自己注意。 
          (2)   mysql中的数值类型(不包括整型):
     IEEE754浮点数: float  (单精度) , double  或 real  (双精度)
    定点数: decimal 或 numeric
    单精度浮点数的有效数字二进制是24位,按十进制来说,是8位;双精度浮点数的有效数字二进制是53位,按十进制来说,是16 位
    一个实数的有效数字超过8位,用单精度浮点数来表示的话,就会产生误差!同样,如果一个实数的有效数字超过16位,用双精度浮点数来表示,也会产生误差
          (3)    IEEE754标准的计算机浮点数,在内部是用二进制表示的,但在将一个十进制数转换为二进制浮点数时,也会造成误差,原因是不是所有的数都能转换成有限长度的二进制数。
    即一个二进制可以准确转换成十进制,但一个带小数的十进制不一定能够准确地用二进制来表示。



三、建议使用UNSIGNED存储非负数值。
     (1)   同样的字节数,非负存储的数值范围更大。如TINYINT有符号为 -128-127,无符号为0-255。
     (2)   便于查询




四、建议使用INT UNSIGNED存储IPV4。
     (1) 用UNSINGED INT存储IP地址占用4字节,CHAR(15)则占用15字节。另外,计算机处理整数类型比字符串类型快。使用INT UNSIGNED而不是CHAR(15)来存储IPV4地址,通过MySQL函数inet_ntoa和inet_aton来进行转化。IPv6地址目前没有转化函数,需要使用DECIMAL或两个BIGINT来存储。 
      例如:
SELECT INET_ATON('209.207.224.40');
3520061480

SELECT INET_NTOA(3520061480);
209.207.224.40





五、 整形定义中不添加长度,比如使用INT,而不是INT(4)。
          (1)    mysql中int数据类型长度最大为11位,最少为4位,不够在前面补空格。
          (2)     而mysql中int本身就是4个字节 bigint是8个字节 所以说int(X)的含义就是 int决定数据存储的字节 X表示期望数据的列宽度
在SQL语句中int代表你要创建字段的类型,int代表整型,11代表字段的长度。
整数列的显示宽度与mysql需要用多少个字符来显示该列数值,与该整数需要的存储空间的大小都没有关系,比如,不管设定了显示宽度是多少个字符,bigint都要占用8个字节。
     
p中将IP转换成整型的函数ip2long
整型转换ip  long2ip




六、使用短数据类型,比如取值范围为0-80时,使用TINYINT UNSIGNED。
       (1)  
                    1、TINYINT ,字段类型,如果设置为UNSIGNED类型,只能存储从0到255的整数,不能用来储存负数
                    2、TINYINT 型的字段如果不设置UNSIGNED类型,存储-128到127的整数。
         提示:   通常,为了节省空间,应该尽可能的使用最小的整型数据。一个TINYINT型数据只占用一个字节,一个INT型数据占用四个字节。这看起来似乎差别不大,但是在比较大的表中,字节数的增长是很快的。另一方面,一旦你已经创建了一个字段,要修改它是很困难的。因此,为安全起见,你应该预测一下,一个字段所需要存储的数值最大有可能是多大,然后选择适当的数据类型。

          (2)
                    
tinyint 1字节 (-128,127)
smallint 2字节 (-32768,32767)
int 无符号 0-65535
mediumint 3字节 (-8388608,8388607)
int或integer 4字节 (-2147483648,2147483647



七、不建议使用ENUM类型,使用TINYINT来代替。
         (1)   TINYINT(1)或ENUM('真','假')?
 用ENUM存储枚举当存储只有2个值时只占用一个位的宽度,0或1,但会花更多的时间去寻找了枚举查询的开始。
 用TINYINT(1)默认就会占用4个位的宽度(0000)
            因此得出结论:
比如要存储一个介于0-9之间的值,为了查询获取这个值,建议用TINYINT(1)会更快,
 但如果你是为了大量记录枚举(“真”,“假”),那么用ENUM( 'true' , 'false') 搜索会更快。

(2)详细讲解:
           说起这个ENUM, 经查阅各大技术社区的网络文摘,ENUM确实是mysql里的一个特色字段,印象里模糊记得在以前看到一些比较知名的商城系统如shopnc里面在用它,但也没细究,可能是因为他可以设置字段的区间范围,会让值可以被数据库所控制,有枚举约束的功能(比如,字段只想有0和1,如果用TINYINT(1),结果就可能出现2,那2就是赃数据了)

      但ENUM也有一些比较棘手的问题,比如数据迁移的时候,他几乎不可能被其他数据库所支持,如果enum里面是字符串,对于其他数据库来说就更郁闷了,还不能设为tinyint等类型的字段(enum虽然可以存储字符串,但对于内部来说,还是以顺序进行索引,比如'a','b','c',我们也可以用索引值来获取值select * from tbl_name whre enum = 2,这与select * from tbl_name where enum = 'b'等义)如果你看明白了这两句SQL为什么等义,那么你也就可以了解为什么不主张用enum字段了。

      也就是说,假如一个设计不合理的ENUM字段,给程序员带来的就完全是梦魇了,比如一个enum字段的范围是('0','1','2','3','4','5'),而enum的枚举值对应的索引是从1开始的,因此,insert into table (enum)values(1),插入的并不是1,而是0

       另外假如你在设计好enum的枚举字段范围并使用了一段时间后,再到字段范围中加一个枚举值,并且不是加在最后,那么也就相当于把原来的范围都改变了索引值,也就是当你在查询的时候直接查询值(并加上单引号),将不会使用enum自身隐藏的索引值来获取结果了。


        如果是纯数值型,还是建议采用tinyint字段吧,毕竟它也只占一个字节,即使出现赃数据,也可以被接受,不象enum,如果纯数字型范围,更改了索引,你就不知道你查询的值是否正确了)

ENUM:          
比如数据迁移的时候,enmu几乎不可能被其他数据库所支持
如果字段是字符串,并且长度固定,可以尝试用char,如果是数值型,还是用tinyint吧,比较安全稳定,而且即使迁移,也不会出现太多问题。
枚举类型ENUM字段定义的值域列表中,元素的数量最大不能超过65535;
枚举类型ENUM字段的每个元素值,可以为数字、字母、特殊符号等,必须用一对单引号或一对双引号括起来;
枚举类型ENUM字段的每个元素值必须为常量值,不允许使用变量、任何函数或表达式;
枚举类型ENUM字段定义的值域列表中,不允许显示出现NULL值;


七、尽可能不使用TEXT、BLOB类型。
     (1)
              1、 BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种 BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。 有4种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。这些对应4种BLOB类型,有相同的最大长度和存储需求。
               2BLOB 列被视为二进制字符串(字节字符串)。TEXT列被视为非二进制字符串(字符字符串)。BLOB列没有字符集,并且排序和比较基于列值字节的数值值。TEXT列有一个字符集,并且根据字符集的 校对规则对值进行排序和比较。
在TEXT或BLOB列的存储或检索过程中,不存在大小写转换
                3、 在大多数方面,可以将BLOB列视为能够足够大的VARBINARY列。同样,可以将TEXT列视为VARCHAR列。BLOB和TEXT在以下几个方面不同于VARBINARY和VARCHA
        注意事项:
                          由于BLOB和TEXT值可能会非常长,使用它们时可能遇到一些约束:
          当排序时只使用该列的前max_sort_length个字节。max_sort_length的 默认值是1024;该值可以在启动d服务器时使用--max_sort_length选项进行更改。
           运行时增加max_sort_length的值可以在排序或组合时使更多的字节有意义。任何客户端可以更改其会话max_sort_length变量的值:



八、VARCHAR(N),N表示的是字符数不是字节数,比如VARCHAR(255),可以最大可存储255个汉字,需要根据实际的宽度来选择N。
          区别:
                    1、char的总结:
                                    char最大长度是255字符,注意是字符数和字符集没关系。可以有默认值,尾部有空格会被截断。
                    2、varchar的总结:
                                      varchar的最大长度65535是指能存储的字节数,其实最多只能存储65532个字节,还有3个字节用于存储长度。注意是字节数这个和字符集有关系。一个汉字字符用utf8占用3字节,用gbk占用2字节。可以有默认值,尾部有空格不会截断。
                   二 理论知识
 先说明一下 MySQL 历来版本对 varchar 的定义:
  4.0版本以下,varchar(50),指的是50字节,如果存放UTF8汉字时,只能存16个(每个中文3字节)
  5.0版本以上,varchar(50),指的是50字符,无论存放的是数字、字母还是UTF8中文(每个中文3字节),都可以存放50个
 存储限制
  需要额外占用字节存放字符的长度:小于255为1个字节,大于255则要2个字节
 编码限制
  gbk :每个字符最多占用2个字节
  utf8:每个字符最多占用3个字节
  utf8mb4 每个字符最多占用4个字节,中文占3个字节,emoji表情符号 占用4个字节
 长度限制
  MySQL定义行的长度不能超过65535,该数值限制了列的数目,比如char(128) utf8字符集,最多有65535/(128*3)=170个汉字。




九、VARCHAR(N),N尽可能小,因为MySQL一个表中所有的VARCHAR字段最大长度是65535个字节,进行排序和创建临时表一类的内存操作时,会使用N的长度申请内存。
             (1)
就中文汉字来说,utf8占3个字节 ,gbk占2个字节。varchar(n),这里的n代表n个字符。
mysql表中字段总长度可以有65535个字节,意思就是 如果一个表只有varchar(n)这么一个字段,而且是utf8的话,那么这个字段最大可以有65535个字节的长度,差不多n=65585/3的字符。
为什么说差不多。因为varchar在存储的时候,会另加一个字节来记录长度(如果列声明的长度超过255字节,则使用两个字节,刚好2的8次方是255,超过255就只能用2个字节16位来记录了)。
如果表中有个char(10)和varchar(n)的话,那么就就这样,n的最大值=65535-10*3,我是这么算的, 虽然最后差1-2个字节,不过不用这么在意吧?除非你有强迫症。呵呵!

英文的话 两种都是一个字母是1个字节。能放多少个可以自己测试的,其中的编码知识,值得研究,但是不值得深究,我感觉太钻牛角尖了。

解决你的问题应该没难度了,char最大才是255个字符,不论什么编码。
varchar 在5.03以前长度可以为0~255, 之后是65535
varchar(2000)正确
varchar(255) 大概可以存255字节的字符串, 中英文占位不同, 字符数也不同




十、表字符集选择UTF8。
         (1) 使用utf8字符集,如果是汉字,占3个字节,但ASCII码字符还是1个字节。
         (2) 统一,不会有转换产生乱码风险
         (3)其他地区的用户(美国、印度、台湾)无需安装简体中文支持,就能正常看您的文字,并且不会出现乱码
         (4)ISO-8859-1编码(latin1)使用了单字节内的所有空间,在支持ISO-8859-1的系统中传输和存储其他任何编码的字节流都不会被抛弃。即把其他任何编码的字节流当作ISO-8859-1编码看待都没有问题,保存的是原封不动的字节流。



十一、使用VARBINARY存储变长字符串。
              二进制字节流,不存在编码问题
            (1)
                    binary(n):固定长度为 n 字节,其中 n 值从 1 到 8,000 ,存储空间为 n 字节;
                    varbinary( n | max):可变长度,n 的取值范围为 1 至 8,000,max 是指最大存储空间是 2^31-1 个字节,即最大4GB;
                    n:在表列定义或变量声明语句中没有指定 n,则默认长度为 1;在CAST 函数中没有指定 n,则默认长度为 30;
               详情:::      http://www.cnblogs.com/ljhdo/p/4530293.html




十二、存储年使用YEAR类型。
    重点:: mysql的日期与时间类型:分为time、date、datetime、timestamp、year,
(1)、类型支持:year 与 year(4),注意无year(2)的定义方式,否则报错“[Err] 1818 - Supports only YEAR or YEAR(4) column.”
create table if  not exists time(
atime  YEAR                         #year的定义,可写成year或者year(4)   
) engine =innodb charset = utf8;
(2)、插入值,支持整数和字符串,支持 2位数 或者 4位数

  00~69  将转换为2000~2069之间

   70~99  将转换为1970~1999之间

#测试year类型insert into time values( 78);    #数据库中显示:1978
insert into time values('78'); #数据库中显示:1978
insert into time values('1978'); #数据库中显示:1978
(3)、注意点
                1、 支持插入 数字0 或者 字符串0,实际显示的数值不同
insert into time  values( 0);  #数据库中显示:0
insert into time values('0'); #数据库中显示:2000
                 2、year只保存年份,占用空间小
                 3、其他和日期有关的可以通过整型保存
时间初  : 存9位


十三、存储日期使用DATE类型。
            MySQL日期类型、日期格式、存储空间、日期范围比较。
日期类型        存储空间       日期格式                 日期范围
------------ ---------   --------------------- -----------------------------------------
datetime       8 bytes   YYYY-MM-DD HH:MM:SS   1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
timestamp      4 bytes   YYYY-MM-DD HH:MM:SS   1970-01-01 00:00:01 ~ 2038
date           3 bytes   YYYY-MM-DD            1000-01-01          ~ 9999-12-31
year           1 bytes   YYYY                  1901                ~ 2155



十四、存储时间(精确到秒)建议使用TIMESTAMP类型,因为TIMESTAMP使用4字节,DATETIME使用8个字节。
      1、DATETIME
日期和时间的组合。支持的范围是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。MySQL以'YYYY-MM-DD HH:MM:SS'格式显示DATETIME值,但允许使用字符串或数字为DATETIME列分配值。
       2、 TIMESTAMP[(M)]
时间戳。范围是'1970-01-01 00:00:00'到2037年。
TIMESTAMP列用于INSERT或UPDATE操作时记录日期和时间。如果你不分配一个值,表中的第一个TIMESTAMP列自动设置为最近操作的日期和时间。也可以通过分配一个NULL值,将TIMESTAMP列设置为当前的日期和时间。
TIMESTAMP值返回后显示为'YYYY-MM-DD HH:MM:SS'格式的字符串,显示宽度固定为19个字符。如果想要获得数字值,应在TIMESTAMP 列添加+0。




十五、建议字段定义为NOT NULL。
          
     (1) 空值是不占用空间的, not null的效率比null高
      (2)  MySQL中的NULL其实是占用空间的  : 打个比方来说,你有一个杯子,空值代表杯子是真空的,NULL代表杯子中装满了空气,虽然杯子看起来都是空的,但是区别是很大的。



十六、将过大字段拆分到其他表中。
     分开 好分析,取数据好取


十七、禁止在数据库中使用VARBINARY、BLOB存储图片、文件等。
           采用分布式文件系统更高效
           (1)
          binary 和 varbinary
固定长度 (binary) 的或可变长度 (varbinary) 的 binary 数据类型。

binary [ ( n ) ]

固定长度的 n 个字节二进制数据。N 必须从 1 到 8,000。存储空间大小为 n+4 字节。 

varbinary [ ( n ) ]

n 个字节变长二进制数据。n 必须从 1 到 8,000。存储空间大小为实际输入数据长度 +4 个字节,而不是 n 个字节。输入的数据长度可能为 0 字节。在 SQL-92 中 varbinary 的同义词为 binary varying。

注释
如果在数据定义或变量声明语句中没有指定 n,默认长度为 1。如果没有用 CAST 函数指定 n,默认长度为 30。

当列数据项大小一致时应使用 binary。

当列数据项大小不一致时应使用 varbinary。
        (2)    
BLOB (binary large object),二进制大对象,是一个可以存储二进制文件的容器。
在计算机中,BLOB常常是数据库中用来存储 二进制文件的字段类型。
BLOB是一个大文件,典型的BLOB是一张图片或一个声音文件,由于它们的尺寸,必须使用特殊的方式来处理(例如:上传、下载或者存放到一个数据库)。
 
大型对象
BLOB就是使用二进制保存数据。
如:保存位图。
CLOB使用CHAR来保存数据。




十八、表结构变更需要通知DBA审核。
        数据库管理员     DBA :::Database Administrator 
          (1) 每次变更不能说变就变了,不然,别人不知道,肯定也是按照原来的来,报错的话,也就不好往下进行了,
                    每次变更,提前说,都知道,审核,DBA觉得合理在审核通过,再把这些变更的,放入一个文件里,便于
                    查看,修改了什么。
平时数据库得维护,管理,看看这设计得是否合理,不合理的更改,





  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值