Mysql数据库表设计

  • 表设计常踩的坑


表设计常踩的坑

上周面试,被面试官问及数据库建表的三大范式,啥,三大范式,你要是问B+树我还能说道说道,回去就去面向搜索引擎查询问题

mysql 查询表设计sql_mysql 查询表设计sql


关于数据建表三大范式介绍,网上有很多,主要就是保证数据库的简洁、结构清晰,同时,不会发生CRUD的操作异常

1NF:字段不可分;

2NF:有主键,非主键字段依赖主键;

3NF:非主键字段不能相互依赖;

1.第一范式:无重复的列(确保每列保持原子性),这是最基本的范式,每个字段都是不可继续拆分的。

具体的范式规则,有很多博客都讲的很详细,此处不过多介绍

但是实际应用中真的要严格遵守三范式么。

直接进入正题,就是平时工作中经常遇到的问题,一个业务表存了一个处理人ID,然后查询的时候需要显示处理人名字,

业务表不冗余存储处理人名字(假设名字会修改),查询的时候也不join用户表(太多这类字段,join在数据量大的时候非常影响性能),那你们是怎么解决这个问题的?

问题一、业务表不冗余存储处理人名字,这个就不符合以上范式了,会增加表的大小,最重要的是假设名字会修改呢?

问题二、查询或修改的时候使用join关联用户表,这个确实符合了范式,但是当数据量大或者关联的表多的时候呢?

sql的好坏与否在于性能可读性

一般来说,不建议表连接,表连接的坏处有几点,

1、查询效率更低(把压力给了更底层的数据库)

2、表之间出现了耦合,将来数据量大,如果分表,还需要修改代码。

3、sql可读性,我常见到有人写一句sql包含了N张表,各种判断条件if、case等等,sql事情是做完了,换个人来维护,看懂估计都要小半天。

优化方案:
一:多级缓存:可以将基础信息放到JVM缓存,或者分布式缓存。尽量减少代码的入侵以及压力的下沉,把压力往上层驱赶,越底层压力越小越合适,能浏览缓存的地方,尽量不使用内存或分布式缓存,能缓存的地方,尽量不要查数据库,尽量让更底层的系统少抗压,越底层(依赖它的人越多,扩容相当麻烦(且容易引起生产事故),秒杀系统就是靠着多级缓存才能抗住大量的请求。
二:事务控制:此处引入一个概念级联修改,不一定是触发器、外键,不要使用触发器(也不使用存储过程与视图),因为它会降低移植性与扩展性,且不可读,不可控。外键约束会影响插入效率,所以尽量让应用程序来解决这些问题,一个事务中修改多张表就好。
三:尽量避免join,当然实际查询是不可能的,使用join的时候,小表驱动大表查询还是很快的,如果处理人那张表数据量不大的,可以作为join的驱动表,阿里给的建议是单表(即非拆分表)之间的 JOIN;
参与 JOIN 的表在过滤条件中均带有拆分键作为条件,并且拆分算法相同(即通过拆分算法计算的数据分布在相同分片上);
参与 JOIN 的表均按照拆分键作为 JOIN 条件,并且拆分算法相同;
广播表(也称为小表广播)与拆分表之间的 JOIN。另外,数据量超过10万行的表的sql语句,都要拿过来explain一下,看是否可以有效命中索引

最后,将基础信息放到jvm缓存中确实是可以做到松耦合,但他也有弊端,比如数据的及时性,分布式环境下不同JVM的同步问题,这个就要扯到Zookeeper了。
如何选取:取决于你的业务需求,应用场景,并发量等等诸多因素。