java岗面试中考察数据库优化以及非关系型数据库redis的使用

本人在学习web开发过程中一直使用MySQL数据库,所以根据自己的经验谈谈如何对MySQL数据库进行优化,水平较低,有错误希望大家指出来,谢谢!
一.数据库的优化
在一些大型项目中,对数据库的读写性能要求较高时,我们需要查找和定位慢查询,并对其优化,优化的方法如下:
(1)创建索引:我们需要创建合适的索引,这样就可以先查询索引,然后直接找对应的记录;
那么我们怎么定位和查找慢查询呢?在项目自验项目转测试之前,在启动MySQL数据库时开启慢查询,并且把执行慢的语句写到日志中,在运行一定时间后,通过查看日志找到慢查询语句。使用explain慢查询语句,来详细分析语句的问题。
(2)分表:当一张表的数据比较多或者一张表的某些字段的值比较多并且很少使用时,我们需要采用水平分表和垂直分表来优化;
我们在设计数据库表需要遵循范式,表的范式是必须符合1NF,才能满足2NF,进一步满足3NF。
1NF:即表的列具有原子性,不可再分解,即列的信息,不能分解,只要数据库是关系型数据库,例如MySQL,Oracle,db2,sql server等等,就自动满足1NF,关系型数据库是不允许分割列的;
2NF:表中的记录是唯一的,通常我们设计一个主键来实现;
3NF:即数据库中的表中不要有冗余数据,通俗地说,表的信息,如果能够被推导出来,就不应该单独设计一个字段来存放(外键)
反3NF:没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据,具体的做法是:在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑,降低范式就是增加字段,允许冗余。在实际应用中,订单和订单项,相册浏览次数和照片的浏览次数设计时需要遵循反3NF。
水平分表即按行分表,MySQL表数据一般达到百万级别,查询效率会很低,容易造成表锁,甚至堆积很多连接,甚至挂了,水平分表可以很大程度上减轻压力。
水平分表的策略如下:
(一)按时间分表,这种分表方式有一定的局限性,当数据有较强的时效性,如微博发送记录,微信消息记录等等,这种数据很少有用户会查询几个月前的数据,可以按月分表;
(二)按区间范围分表:一般在有严格的自增id需求上,如按照user_id水平分表;
(三)hash分表:通过一个原始目标的Id或者名称通过一定的hash算法计算出数据存储表的表名,然后访问相应的表。
(3)读写分离:当一台数据库服务器不能满足需求时,我们需要采用读写分离的方式进行集群;
一台数据库服务器支持的最大并发连接数是有限的,如果用户并发访问太多,一台服务器无法满足需求时,我们需要集群处理,Mysql的最常用的集群处理技术就是读写分离,其关键步骤分为主从同步和读写分离。
主从同步:数据库最终会把数据持久化到磁盘上,如果集群必须确保每个数据库服务器的数据是一致的,能改变数据库数据 的操作都往主数据库去写,而其他的数据库从主数据库上同步数据。
读写分离:使用负载均衡来实现写的操作都在主数据库服务器上完成,而读的操作在从数据库服务器上完成。
(4)使用缓存:比较常用的方法是使用非关系型数据库redis来进行缓存;
在持久层(dao:data access object)和数据库之间添加一个缓存器,如果用户访问的数据已经缓存起来,用户再次访问时可以直接从缓存中获取,不用访问数据库,而缓存是在内存完成的,访问速度快。
作用:减轻数据库服务器压力,减少访问时间。
Java中常用的缓存有:hibernate的二级缓存,但是该缓存不能完成分布式缓存,最常用的是使用redis或者memcache作为中央缓存,对缓存的数据进行集中处理。
(5)一些常用的优化技巧。
DDL优化:
(一)通过禁用索引来提供导入数据性能,这个操作主要针对有数据库的表添加数据
第一步:去除key;
第二步:批量插入数据;
第三步:恢复key。
(二)关闭唯一校验
(三)修改事务提交方式(导入)即变多次提交为一次

DML优化(变多次提交为一次):
例如
insert into test values(1,2);
insert into test values(1,3);
insert into test values(1,4);
我们可以合并为一条insert into test values(1,2),(1,3),(1,4);

DQL优化
order by 优化
1.多用索引排序;
2.普通结果排序(非索引排序)
group by 优化是使用order by null 取消默认排序
最常用的还是DDL优化和DML优化

二.redis简单介绍和使用场景
redis是一个key-value的nosql数据库,先存到内存中,会根据一定的策略持久化到磁盘,即使断电也不会丢失数据,支持的数据类型比较多。主要用来做缓存数据库和web集群时作为中央缓存存放session,关于session我在上一篇博客中做了简单的介绍,因为自身的水平较低,所以写的都是皮毛。
redis的使用场景:
(1)缓存:把经常需要查询的,很少修改的数据,放到读速度很快的内存空间中,以便下次访问减少访问时间,减轻服务器压力;
(2)计数器:redis中的计数器是原子性的内存操作,可以解决库存溢出问题,进销存系统库存溢出。
(3)session缓存服务器:web集群时作为session缓存服务器,缓存队列等

redis对象保存方式
如果是数据完全可以使用JSON方式,redis直接set get使用起来门槛较低,redis没有提供专门的设置对象方法,需要自己进行改写。如果担心JSON转对象会消耗资源的情况,这个问题需要考虑几个方面,第一,使用的JSON转换lib是否就会存在性能问题;第二:数据的数量级级别,如果是存储百万级的大数据对象,建议采用存储序列化对象方式,如果是少量的数据级对象或者数据对象字段不多,还是建议采用JSON转换成String方式。

redis的数据淘汰机制
在redis中,允许用户设置最大使用内存大小,在内存限定的情况下是很有用的,假如在一台8G内存的服务器上部署了4个redis服务点,每个服务点分配1.5G的内存大小,减少内存紧张的情况,由此获取更为稳健的服务。redis内存数据集大小上升到一定大小的时候,就会执行数据淘汰策略,redis提供了6种数据淘汰策略:volatile-lru,volatile-ttl,volatile-random,allkeys-lru,allkeys-random,no-enviction
java访问redis
我们可以使用jedis.java客户端来访问redis服务器,有点类似通过jdbc访问mysql一样,如果是spring集群,可以使用spring data来访问redis,spring data 只是对jedis的二次封装。当一台redis数据库服务器无法满足需求时,我们可以使用redis集群来处理,这有点类似MySQL的读写分离。
希望大家积极指出错误,一定改正,谢谢!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值