大家在实际项目应用的时候 ,查询数据,以及查询数据量,以及查询数据快慢是查询的关键。
所以在优化查询,提高查询效率就变成了重中之重,首先我们要了解查询所要经历的过程,首先是项目的编译启动,进程运行,用户访问,数据查询,数据的耗能,以及数据反馈等。
我这里只说能够用到的地方,以及本人知道的。如有更好的也请各位大神多多指教。
系统编译过程也就是我们 jvm 虚拟机编译的过程,jvm 中也是有缓存区的,jvm 是内存中的一部分,他的存储数据有几部分
第一步 寄存器是最快的区域cache 2 堆栈区域 也就是我们java 中的数据类型,方法等存储区域, 3 静态变量等 如果要求数据快速返回,以及数据量固定且不会很大时可使用static 变量,使用static 来操作。利用内存区域来使用虽然较为快速,但是对于空间要求较高。jvm 直接内存区域也可以存储数据 存储空间大概为4M 。
第二步,请求到了方法区内 ,可以利用大家熟识的 redis 缓存等,或者MongoDB ,非关系型数据库,来快速查询,注意当我们数据量较大的时候 我们设置缓存的时候需要注意的几点, 雪崩问题,穿透问题。
第三步 我们经常使用的spring 也是有缓存的注解
- @Cacheable
- @CachePut
- @CacheEvict
- @Caching
第四步 当以上数据都无法满足时可以利用持久层的 有自己的一套 二级缓存 和一级缓存,此处适用于统计数据且数据在一定时间内不会变动,
第五步 sql 优化 : 经常有人说少用子查询等等, 对于现在例如 mysql 5.0 以上版本来说, 子查询其实对于数据库查询效率没有任何影响 只是子查询相当于多一个虚拟表增加数据库的空间压力,(这里单独再说一点别的,很早以前做的一些项目数据表都是char 类型的,为什么要用char 呢 他们都是固定长度,不想我们现在常用的varchar 数据库有这样一句话 空间消耗大 查询效率高 空间消耗小 查询效率 就低了)所以说 left join 对我们来说 和 子查询是相同的,查询 尤其是我们遇到一些统计的时候 ,经常用到聚合函数 sum 等操作 如果你用到了 其他的 一些判断条件 例如 ifnull 你要知道 if 与sum 之间的优先级 以及sql 解析时候的先后顺序。对于你sql优化是很有帮助的。还有就是正确的索引也是重要的,索引也不是越多越好,是占物理空间的,一个表大概六个左右就差不多了。
第六步 对数据表的处理,分库分表 这是我们经常用到的, 那么如何分库分表呢。一般来说 分为水平切分 和垂直切分 , 垂直切分 意味着按照业务场景来切分,例如 你的订单业务,和你的快递业务 较为独立,可以分为两个库 ,水平切分 按照 某个表中的关键字 区分, 例如支付宝有一个 交易流水表 每天看到几十亿数据 按照什么来划分呢 ,你又要看到 支付人 和收款人信息, 这里是距离 场景并不是很明确 ,例如我按照 地区划分 所有的省市直辖市 都有自己独立的交易表查询效率是不是就很快了。后期看到数据的走向 例如北京数据很多 还需要分表 那么可以根据具体的情况再进行划分。