在开发中警用会遇到查询很慢的问题,尤其是当数据量上去的时候,那么我们就要开始优化我们的程序or
数据表
1:一般针对表结构进行优化,采用中间表
2:优化sql,使用索引,
3:利用MySQL主从做读写分离
四:采用缓存机制,
5:垂直节分,从实际业务上进行拆分,比如电商网站一般都是广告,大家电,小家电之类的拆开
6:水平切分,针对一张表进行节分,这样保证了不会出现一张表太大情况,但是要做好路由规则,现在一般都采用的一致性哈希算法进行路由。
下面挨个分析:
1:一般针对表结构进行优化,采用中间表
第一条,针对表结构进行优化,再设计表的时候并不是按照数据库三范式,我们一般采用的是这种的方式设计表,
第一范式:数据表中的每一行都是不可分割的原子列,
比如有一个选课的表 Student_Course(studentId, studentName, collegueId, collegueName, courseId, courseName, grade, credit, courseId1, courseName1, grade1, credit1)
这样子如果增加了新的课程没有可扩展性。
为了满足第一范式,我们的设计结果不能使用一个courseName然后用,号分割。 没有可读性,查询起来也很麻烦。
只能有重复的行了,Student_Course(studentId, studentName, collegueId, collegueName, courseId, courseName, grade, credit)
这样就需要用联合主键了studentId和courseId决定了一条记录
第二范式:实体属性完全依赖于主键关键字。 他要求数据库表中的实例或行必须被唯一区分,为实现他的分区,通常为表加一列,以存储每个表的唯一标示,这一列一般都是主键列
就是像上面这种情况使用联合主键的,
(studentId, courseId) -> grade
studentId -> studentName, collegueId, collegueName
courseId -> courseName, credit
会有如下的问题:
数据冗余: 如果一个人选择了N门课,就会造成studentName, collegueId, collegueName,courseName, credit这些都重复n次
更新异常,如果修改了credit,那么需要修改所有记录的,有可能造成同一个课程学分不同
插入异常,如果新开一门课程,如果没人选修则无法插入
删除异常,如果选修完了,那么课程也同样要删除掉。
修改的办法为修改为三个表
Student(studentId, studentName, collegueId, collegueName)
Course( courseId1, courseName1, credit1)
Student_Course(studentId, courseId, grade)
第三范式: 非主属性对候选关键字没有传递依赖 一对多
studentId-> collegueId -> collegueName 且 collegueId-> studentId(不是一对一)
Student 这张表有问题, 同样会带来2Nf的那些问题。 可以再单独分离为一个类,变为
Student(studentId, studentName, collegueId)
collegue(collegueId, collegueName)
范式的缺点:范式为了消除冗余列,会增加表数据增加了查询的复杂度,其实可以适当使用冗余列来提高查询速度
优点:节约空间,会提供更丰富的查询选项
因此我们再设计表的时候要允许一定的冗余列存在。
2:优化sql,使用索引
1):应该避免select * 这样的操作,因为他是全局检索的
2):where 和join的字段应该有索引,应当注意的时候,join在主键和外键数据类型相同的时候,如果值一样就更好
3):在like的时候,如果第一个字符是通配符,那么索引将会失去作用
4):使用函数的时候,索引会失去作用
5):少使用!=,因为在这个操作中,索引是失效的
6):索引应当建在update少的字段上,而且重复数据不多的字段上,这样才会更高效
7):如果在用order by时候有多个字段,可以考虑使用复合索引
...还有很多
索引是有mysql的引擎支持的,因此引擎不同,索引支持的类型可能就不同,以InnoDB来说支持聚簇索引,但是MyISAM只支持全文索引
三:读写分离
一般业务量上去了,就会做mysql的主从,读写分离,写操作主库,读操作从库,可以最大限度的利用现在资源,
关于具体操作有很多,有事基于Mybatis的动态数据源切换的,还有阿里的Cobar和Mycat中间件都可以。
四:缓存机制
现在一般都是使用NoSql数据库作为数据库前端的缓存,一般吧首页,经常用来查询的数据放在缓存中,采用消息机制保证缓存的一直性,同时为了避免缓存击穿,可以把一些值存为null
五:垂直切分
垂直切分就是从业务层次进行考虑,把业务拆分为多个,上面所说经的电商的,广告,小家电,大家电,日化等分库存储,但是这也带来join的问题,无法跨库join,一般是从程序层面去解决,这样优点就是减少了库的并发
六:水平切分
表级别的切分,这样好处就是不会出现太大的表,表与表之间可以直接join,缺点就是分片规则不好定,分片带来事务也不好解决
你会发现在垂直切分和水平切分的时候都会带俩分布式一致性的问题,还有不同节点join的问题,此外还有读取排序的问题
因此我们最好就是采用靠谱的中间件进行,因为那样对开发人员来说是无感觉的,基于mysql的协议,我们认为就是读一个库,由中间件进行复杂的处理,还有就是能不分的就不分,能不join的就不join