数据库的优化分为好多个层次
- 语句上的优化
- 尽量不要使用多表查询、尽量不要使用各种神奇的统计查询、如果需要使用的时候建议使用子查询来代替
- 使用索引
- 空间换时间、时间换空间,是不是频繁的写操作。
- 读写分离
- 分库分表
- 引入搜索引擎
nosql可以实现文档存储、缓存、图像存储。
- 文档型:替换传统开发中的多表查询,把结果当成一个文档存储下来,例如mongoDb
- 缓存型:存储数据,如验证码,例如redis
对数据库做集群,会有同步问题,比较好的是读写分离和分库分表,以及对高频数据做缓存,对缓存数据库做集群。流量的的时候要考虑引入大数据平台和分析系统。
避免使用存储过程
读取数据的一般流程,将硬盘上的数据加载到内存后再通过内存进行读取。因为硬盘上所保存的都是物理上的二进制数据。大量人访问的时候如果通过数据库访问(硬盘上读取)速度就会很慢。换固态硬盘速度会有所提高。但还是有内存与内存间读取的延时。
不读取硬盘上的内容,速度就很快了。比如直接使用内存进行缓存。缓存的核心意义,为了减少数据库的操作。
思考
- 缓存是否数据库专用的缓存
- 缓存是否进行分布式或反向代理的时候使用的(cdn)
- 缓存是否采用缓存数据库(如redis)
解决方案
- 对强一致要求比较高的,应采用实时同步方案,即查询缓存查询不到再从DB查询,保存到缓存;更新缓存时,先更新数据库,再将缓存的设置过期(建议不要去更新缓存内容,直接设置缓存过期)。
- 对于并发程度较高的,可采用异步队列的方式同步,可采用kafka等消息中间件处理消息生产和消费。
- 使用阿里的同步工具canal,canal实现方式是模拟mysql slave和master的同步机制,监控DB bitlog的日志更新来触发缓存的更新,此种方法可以解放程序员双手,减少工作量,但在使用时有些局限性。
- 采用UDF自定义函数的方式,面对mysql的API进行编程,利用触发器进行缓存同步,但UDF主要是c/c++语言实现,学习成本高。
悲观锁的本质是数据库自身所具备的一种处理机制,在数据库的事务里面有个隔离型的概念,其主要主要特征就是当一个session操作某条数据额时候,其它的session是无法操作该数据的,这是数据库自身具备的。
乐观锁不使用数据库自身的特性,利用辅助字段版本号version实现。
所有的程序执行最终都需要CPU完成,但是CPU不能够直接操作硬盘文件系统,而是要把数据先从硬盘写入内存,这个时候就有寻址的问题,缓存就是用来解决内存和硬盘文件系统转换的问题。
关于缓存的思考?
- 哪些数据需要保存在缓存里?
- 热点、高频
- 不用的数据什么时候清理掉?
- JVM GC 4中引用类型
- 常用算法:LRU、FIFO
- 是否需要同步?
- 一般是只读的模式,不会进行更新
缓存的形式
- 文件缓存:将一些数据保存在文件里面,避免动态生成
- 内存缓存:将数据缓存在内存中
- 缓存数据库上(Nosql数据库):redis
数据库的数据源的设置(DataSource)它存在的目的是为了解决数据库的频繁打开与关闭所带来的性能损耗。所以这种不进行重复打开与关闭,以及控制连接人数的做法就称为数据源。
数据源配置的两种方式:
- 容器配置(Tomcat、WebLogic、WAS)
- 程序配置(Spring中使用C3p0)
现在的开发基本上都会考虑使用程序配置了,旧时代程序配置,只是实现了数据库连接池的处理,新时代,例如阿里druid数据源,它可以实现监控操作。
Spring中提供了4种不同形式的数据源配置方式:
- Spring自带的数据源(DriverMangerDataSource);
- DBCP数据源;
- C3P0数据源;
- JNDI数据源。
不管如何处理,数据源都是为了提升数据库操作性能做的一种方案,本质的核心思想;避免了数据库频繁的打开和关闭的处理。
从数据库中(mysql)随机获取几条数据很简单,但是如果一个表的数据基数很大,比如一千万,从一千万中随机产生10条数据,那就相当慢了。
通过mysql最大值函数max(),最小值min()来减小查询消耗
因为mysql数据的最大值和最小值的获取几乎是0消耗的,数据库表数据与自身主键ID的集合做join查询,是非常快速的。刚我也试了一下,在16万数据的基数下,随机产生5条数据几乎看不到时间消耗的。但是这种查询方法有一个缺点,产生的数据ID都是连续的,如果想不连续,还要做循环执行才行(每循环一次随机1条或2条数据)。
SELECT sh1.* FROM fw_share AS sh1
JOIN
(SELECT
ROUND(
RAND() * ((SELECT MAX(share_id) FROM fw_share)-(SELECT MIN(share_id) FROM fw_share))
+ (SELECT MIN(share_id) FROM fw_share)
) AS share_id
) AS sh2
WHERE sh1.share_id>=sh2.share_id
其实通过有根据的随机产生,通过有索引的其它字段,如通过标题等,缩小范围进行随机。