1。命名约定数据库表名、字段名、索引名等都需要命名约定,可读性强(一般需要英文),这样别人一看命名就知道这个字段是什么意思。比如一个表的account字段,反例如下:acc_no,1_acc_no,zhanghao正例:account_no,account_number表名和字段名必须使用小写字母或数字,禁止以数字开头,禁止使用拼音,一般不使用英文缩写。主键索引名称为pk_fieldname;唯一索引名称是uk_field名称;公共索引名称是idx_field名称。2、选择合适的字段类型在设计表的时候,我们需要选择合适的字段类型,例如:尽可能选择存储空间小的字段类型,就像数字类型一样,从tinyint、smallint开始,int,bigint从左到右如果选择amount等小数类型,就选择decimal,禁止使用float和double。如果存储的字符串长度几乎相等,则使用char定长字符串类型。varchar是不预分配存储空间的变长字符串,长度不能超过5000。如果存储的值太大,建议将字段类型改为text,同时提取一个单独的表,并使用主键与之对应。在同一个表中,所有varchar字段的总长度不能大于65535,如果有这样的要求,请使用TEXT/LONGTEXT类型。3、主键设计如果主键设计合理,最好不要和业务逻辑关联。虽然有些业务字段,比如身份证,是唯一的,但是有些开发者喜欢把它作为主键,但是不推荐。主键最好是一串无意义的独立不重复的数字,比如UUID,或者Auto_increment自增的主键,或者雪花算法生成的主键等;4、选择合适的字段长度先问大家一个问题,你知道数据库字段的长度是指字符的长度还是字节的长度?其实在mysql中,varchar和char类型代表的是字符的长度,而其他类型代表的长度代表的是字节的长度。比如char(10)表示字符长度为10,bigint(4)表示显示长度为4字节,但由于bigint实际长度为8字节,所以bigint(4)实际长度为8字节。我们在设计表的时候,要充分考虑一个字段的长度,比如一个用户名字段(它的长度是5-20个字符),你觉得应该设置多长?考虑设置为用户名varchar(32)。字段长度一般设置为2的次方(即2的n次方)。’;5.优先考虑逻辑删除而不是物理删除。什么是物理删除?什么是墓碑?物理删除:将数据从硬盘中删除,释放存储空间逻辑删除:在数据中添加一个字段,如is_deleted,标记该数据已被逻辑删除。物理删除是执行删除语句,比如删除account_no='666'的账户信息SQL如下:deletefromaccount_info_tabwhereaccount_no='666';逻辑删除,是这样的:updateaccount_info_tabsetis_deleted=1whereaccount_no='666';为什么推荐逻辑删除,不推荐物理删除?为什么不建议使用物理删除,因为很难恢复数据?物理删除会使自增主键不再连续。核心业务表中的数据不建议物理删除,只适用于状态变化。6、每张表都需要添加这些通用字段,如primarykey、c??reate_time、modified_time等表。一般来说,还是有这几个字段:id:主键,一张表必须有主键,必须create_time:创建时间,必须是modified_time/update_time:修改时间,必须,更新记录时,需要更新版本:数据记录的版本号,用于乐观锁,不需要remark:数据记录备注,不需要modified_by:修改人,不需要creator:不需要创建者7.一张表的字段不要太多当我们建一个表,一定要记住一个表的字段不要太多,一般尽量不要超过20个字段。笔者记得在上一家公司,一个合伙人设计了一个开户表单,添加了50多个字段。..如果一个表的字段太多,表中存储的数据可能会很大,查询效率会很低。因此,不要在一张表中设计太多的字段。如果业务需求确实需要很多字段,可以将一张大表拆分成多个主键相同的小表。当表的字段数非常多时,可以将表分成两张表,一张作为条件查询表,一张作为明细内容表(主要是出于性能考虑)。8、尽量使用notnull来定义字段。如果没有特殊原因,一般建议将字段定义为NOTNULL。为什么?首先,NOTNULL防止空指针问题。其次,NULL值存储也需要额外的空间,这也会导致更复杂的比较操作,使优化器难以优化SQL。NULL值可能会使索引失效。如果默认情况下将字段设置为空字符串或常量值没有区别并且不影响应用程序逻辑,则将字段设置为NOTNULL。9.设计表时,评估哪些字段需要建立索引首先,评估你的表中的数据量。如果你的表的数据量只有几十行,是不需要加索引的。否则在设计表的时候,如果有查询条件的字段,一般都需要创建索引。但是索引不能滥用:索引不要建太多,单表索引一般不要超过5个,因为建的索引太多会降低写入速度。不能索引具有低区分度的字段。创建性别等索引后,需要注意避免索引失效。比如使用mysql的内置函数,如果索引过多会导致索引失效,可以使用联合索引的方式进行优化。然后,索引也有一些规则,比如覆盖索引,最左匹配原则等等。.假设你创建一个新的用户表如下:CREATETABLEuser_info_tab(`id`int(11)NOTNULLAUTO_INCREMENT,`user_id`int(11)NOTNULL,`age`int(11)DEFAULTNULL,`name`varchar(第255章对于这张表,很可能是根据user_id或者name信息来查询用户,user_id是唯一的。因此,可以给user_id加一个unique索引,给name加一个普通索引。CREATETABLEuser_info_tab(`id`int(11)NOTNULLAUTO_INCREMENT,`user_id`int(11)NOTNULL,`age`int(11)DEFAULTNULL,`name`varchar(255)NOTNULL,`create_time`datetimeNOTNULL,`modifed_time`datetimeNOTNULL,PRIMARYKEY(`id`),KEY`idx_name`(`name`)USINGBTREE,UNIQUEKEYun_user_id(user_id))ENGINE=InnoDBDEFAULTCHARSET=utf8;3NF,通过冗余业务字段减少表关联什么是数据库的三种范式(3NF),大家还有印象吗?第一范式:对于属性的原子性,要求属性是原子的,不能分解;第二种范式:对于记录的唯一性,要求记录具有唯一标识,即实体的唯一性,即不存在部分依赖;第三范式:方法:对于字段的冗余,要求任何字段不能从其他字段派生,要求字段之间不存在冗余,即不存在传递依赖;我们在设计表与字段的关系时,尽量满足第三范式。但有时,适当的冗余可以提高效率。比如下表是产品名称、产品型号、单价、数量、总金额、手机华为8000540000及以上,这是存储产品信息的基础表。总金额字段的存在说明表的设计不满足第三范式,因为可以通过单价*数量得到总金额,说明总金额是冗余字段。但是加入总量这个冗余字段可以提高查询统计的速度,也就是用空间换取时间的做法。当然,这只是一个小例子。你在开发设计的时候,一定要结合具体的业务分析。11.避免使用MySQL保留字。如果库名、表名、字段名等属性中包含保留字,则SQL语句必须使用反引号来引用属性名,这会使SQL语句的编写、shell脚本中变量的转义等变得非常复杂.所以,我们一般避免使用MySQL保留字,如select、interval、desc等。12、不要搞外键关联,一般在代码中维护。什么是外键?外键,也称为FOREIGNKEY,是用于将两个表连接在一起的键。FOREIGNKEY是一个表中引用另一个表中的PRIMARYKEY的字段(或字段集合)。它用于确保数据的一致性和完整性。阿里的Java规范也有这么一条:【强制】不允许外键和级联,所有的外键概念都必须在应用层解决。为什么我们不推荐使用外键?使用外键时存在性能问题、并发死锁问题、使用不便等问题。每次做DELETE或者UPDATE的时候,都要考虑外键约束,这会造成开发难度,也不方便从测试数据创建数据。还有一种场景不能使用外键,就是分库分表。13.一般选择INNODB存储引擎。建表需要选择存储引擎。我们一般选择INNODB存储引擎。除非读写比小于1%,否则考虑使用MyISAM。有的朋友可能会有疑惑,不是还有MEMORY等其他存储引擎吗?什么时候使用它?其实其他的存储引擎一般都是推荐在DBA的指导下使用的。我们来回顾一下三种MySQL存储引擎的对比和区别:特性INNODBMyISAMMEMORY事务安全支持None无存储限制64TB有空间使用HighLowLow内存使用HighLowHigh插入数据速度LowHighHigh是否支持外键SupportNoneNone.选择合适的统一字符集。数据库库、表、开发程序等都需要统一的字符集,通常在中英文环境下使用utf8。MySQL支持的字符集有utf8、utf8mb4、GBK、latin1等utf8:支持中英文混合场景,国际认可,3字节长度utf8mb4:完全兼容utf8,4字节长度,一般需要存储emoji表达式。GBK:支持中文,但不支持国际通用字符集,2字节长度latin1:MySQL默认字符集,1字节长度15如果你的数据库字段是枚举类型,需要注释清楚如果你设计的数据库字段是枚举类型,需要在注释后注释清楚每个枚举的含义,方便维护。例如:`session_status`varchar(2)COLLATEutf8_binNOTNULLCOMMENT'会话授权状态00:在线-授权状态有效01:离线-授权状态无效02:离线-自愿退出03:离线-在别处登录'反例:`session_status`varchar(2)COLLATEutf8_binNOTNULLCOMMENT'sessionauthorizationstatus'并且,如果你的枚举类型在以后的版本中有增加或者修改,也需要在注释后面同时维护。16、时间类型的选择我们在设计表的时候,一般需要添加常用的时间字段,比如create_time、modified_time等。那么我们该如何选择时间类型呢?对于MySQL来说,主要有date、datetime、time、timestamp和year。date:表示的日期值,格式yyyy-mm-dd,范围1000-01-01到9999-12-31,3字节time:表示的时间值,格式hh:mm:ss,范围-838:59:59到838:59:59,3bytesdatetime:表示的日期时间值,格式yyyy-mm-ddhh:mm:ss,范围1000-01-0100:00:00to9999-12-3123:59:59`,8字节,与时区无关timestamp:表示的时间戳值,格式为yyyymmddhhmmss,范围为1970-01-0100:00:01至2038-01-1903:14:07,4字节,与时区年份:年份值,格式为yyyy。Range1901to2155,1byte建议使用datetime类型保存日期时间,因为保存范围更大,与时区无关。17、不推荐使用Storedprocedure(包括存储过程、触发器)。什么是存储过程一个或多个已预编译为可执行过程的SQL语句。什么是触发器触发器是指当事件被触发时自动执行的一段代码。使用场景:可以通过数据库中的相关表实现级联变化。实时监控表中某个字段的变化需要相应的处理。例如,可以生成一些业务编号。注意不要滥用,否则会给数据库和应用程序的维护带来困难。对于MYSQL,存储过程、触发器等都不是很成熟,也没有完善的错误记录处理,所以不推荐使用。18.1:N关系的设计在日常开发中,1对多的关系应该是很常见的。例如,一个班级有多个学生,一个部门有多个员工,等等。这种建表原理是:在从表(N这一边)创建一个字段,将该字段作为外键指向主表(1这一边)的主键。示意图如下:student表是一个多(N)方,会有一个字段class_id存放class表的主键。当然,易伴并没有外键约束,只是简单的保存了这段关系。有时当两个表之间存在N:N关系时,我们应该消除这种关系。通过添加第三个表将N:N更改为两个1:N。比如书籍和读者就是典型的多对多关系。一本书可以被多个读者借阅,一个读者可以借阅多本书。我们可以设计一个借阅表,包括图书表的主键,读者的主键,借还标记等字段。19、大字段在设计表时,我们需要特别注意一些大字段,即占用存储空间较多的字段。比如记录用户评论的字段,或者记录博客内容的字段,或者存储合约数据的字段。如果直接将表字段设计为文本类型,会浪费存储空间,查询效率低下。在MySQl中,这样保存的设计方案其实是不合理的。这种非常大的数据可以保存在mongodb中,然后在业务表中保存mongodb对应的id。这种设计思路类似于为什么我们在表格字段中保存图片时,为什么不保存图片内容,而是直接保存图片url。20、考虑是否需要分库分表。什么是分库分表?分库:一个数据库被分成多个数据库,部署到不同的机器上。分表:将一个数据库表分成多个表。我们在设计表的时候其实可以提前预估是否需要分库分表。比如一些用户信息,如果未来数据量可能达到百万级,设置成千万级,可以提前考虑分库分表。为什么要分库分表:如果数据量太大,SQL查询会变慢。如果一条查询SQL漏掉了索引,千万级数据量的表可能会拖垮整个数据库。即使SQL命中了索引,如果表的数据量超过1000万,查询速度也会明显变慢。这是因为索引一般是B+树结构。如果数据有千万级别,B+树的高度会增加,查询会变慢。分库分表主要包括水平拆分和垂直拆分。拆分策略包括range范围和hash取模。分库分表主要有这几个问题:事务问题跨库关联排序问题分页问题分布式ID21,而是选择一个特定的字段。如果知道只有一条查询结果或者只有一条最大/最小记录,建议使用limit1。尽量避免在where子句中使用or来连接条件。注意优化limitdeeppagination问题。使用where条件限制查询要查询的数据,避免返回冗余行尽量避免对索引列使用mysql内置函数尽量避免在where子句中对字段进行表达式操作尽量避免使用!=或<>运算符在where子句中使用union建立索引时,要注意索引列的顺序,一般遵循最左匹配原则。为了优化查询,您应该考虑在where和orderby涉及的列上建立索引。如果插入的数据过多,可以考虑批量插入。在适当的时候,使用覆盖索引并使用explain来分析你的SQL计划。
