Mysql数据库表设计及查询优化方案

Mysql数据库表设计

表设计常踩的坑

上周面试,被面试官问及数据库建表的三大范式,啥,三大范式,你要是问B+树我还能说道说道,回去就去面向搜索引擎查询问题
在这里插入图片描述
关于数据建表三大范式介绍,网上有很多,主要就是保证数据库的简洁、结构清晰,同时,不会发生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了。
如何选取:取决于你的业务需求,应用场景,并发量等等诸多因素。
此处多多感谢罗厚风老哥的谆谆教导(☄⊙ω⊙)☄

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值