学习和实践往往有很大的不同,而这些技巧也只有在企业中才可以学到。如果在工作的路上有高人指导,肯定会事半功倍。但大多数都没有这样的机遇,只好以梦为马,以书为基,在程序员的道路上不断披荆斩棘,克服困难,勇往直前。今天记录一次公司的技术分享,让我明白了,原来数据冗余也是一个利器。
数据库范式
在上学学习数据库的时候肯定都是要讲到范式的,这里简单回顾一下。
-第一范式(1NF)
所有的域都应该是原子性的,即数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项,即没有重复域。
-第二范式(2NF)
在满足第一范式的基础上,要求数据库表中的每个实例或记录必须可以被唯一地区分。
-第三范式(3NF)
在满足第二范式的基础上,任何非主属性不依赖于其它非主属性。
一定的冗余可以提升性能
冗余是指在一个数据集合中重复的数据称为数据冗余。
1.空间换时间
有一张字典表 city 其中有 id 和 cityName 两个字段,有一张业务表,其中有 id 、cityId、XXX、XXX…字段。
如果查询业务表的话,就必须 join 一下 city 字典表,如果业务表很大很大,那么就会查询的很慢,这个时候我们就可以使用冗余来解决这个问题,直接将业务表中的 cityId 更换成 cityName,这样我们在查询业务表的时候就不需要去 join 那一张 city 的字典表了。这样的方式显然是不符合我们数据库设计的范式的,但是这样的冗余或许很有必要。
2.查询某一个状态值数据
业务表中有一个字段 status 用来存储提交和未提交,假设这张表中未提交的数据相对于提交的数据是很少的,当用户查询所有未提交的数据的时候,就需要在全部的数据,然后筛选出未同意的数据。如果这张业务表非常的庞大,那么这样的查询的效率就非常的慢。
这个时候我们就可以把这张业务表中的未同意的数据冗余到一张新表中,这样用户查询未提交的数据的时候就可以直接在这张未提交的表中查询,查询速度提交很多。
3.拆分活跃数据和不活跃数据
某业务表有这样的一个特点,用户往往都在查询最近三个月(或几个月的)数据,数据每天都在增长,由于数据库表的增长,查询变得原来越慢,性能遇到瓶颈。这个时候可以根据业务将这张表拆分成三个月内数据和三个月外数据,其中三个月外数据还可以按照年份(或月份或季度)拆分成不同的分片。这样用户的查询会大量的命中与三个月内的那张表中,而这张表的数据是有限的,并且数据量并不会特别大,从而解决性能的瓶颈。
4.汇总数据单独存放
某业务表存放着每天的交易数据,用户有的时候想查看某个季度,某一年份的交易总额。几个用户还好,当用户量增加,查询数增加,那么实时查询的方法已经满足不了要求,这个时候我们可以将这一类的汇总数据单独的存放到一张表中,通过在夜间用户量较少的时候计算出来,当用户再次查询的时候我们直接显示这张汇总表中的数据,而不通过查询交易数据表实时计算,这样可以大量的提高性能。
在刚刚工作的时候我心里还抱怨说公司数据库设计的一点都不好,大量的数据冗余,这么连第二范式都不符合呢?这里应该使用外键链接啊…现在才明白自己当时是多么的无知。最近一直在反思自己是不是太浮躁,在别人面前班门弄釜,或许真的应该“将肉扣在碗底吃”?好好钻研技术,该说的就说,不该说的坚决不说。