当我需要去做优化时,有一个固定的优化思路:SQL优化->索引优化->分区优化->优化器hints优化
SQL 语句优化:
1.如有 子查询 但是没有with as 临时表,优先考虑用with as临时表,来代替子查询,不仅增加代码的易读性,更重要的是临时表是一次扫描,多次使用,这也是提升性能的原因-达到了'少读'的目标;
2.就是select,select后面避免使用*,查什么字段就写什么字段,因为使用*是走全表扫描的,不走索引
3.最有效率的表名顺序,oracale的解析器按照从右到左的顺序处理FROM子句中的表名,所以把数据记录最少的放在最后面,如果有三张表以上的表,那就把交叉表放在最后面;
4.,join 之前先去重或者过滤一下,这样join时连接表的数据量更少,连接过程就优化了
5.然后where过滤也是有顺序的,优先吧过滤数据更多的条件放在最后面,避免去使用模糊查询like,in,exists,not等以及避免一些索引列上进行计算,这类情况下会造成索引失效,走全表扫描,增加I/O读取次数。
索引优化:
1.需要建索引的情况,经常需要搜的列,建索引可以加快查询速度,经常需要join连接的列,建索引可以加快连接速度,经常使用where的子句中的列,建索引可以加快判断速度,经常group by,order by 的列,建索引可以加快排序的速度
分区优化:
如果原表是没有建分区的话,会考虑重新创建一个一模一样的表并选择合理的分区方式,分区的方式有范围分区,列表分区,哈希分区,组合分区,interval分区,然后再把数据导进来,alter table rename 来修改原表名字成为历史表,再修改新表名字成为需求表
考虑到 数据量过于大了,可以先考虑先分表再分区提升性能,分表是通过定时任务,使用存储过程执行动态sql实现每年or每半年,每季度,根据实际情况来定,进行分表存储,每年的数据存储在对应的分表之中,如果数据量还是大,就要考虑到分区了,这个时候可以选择按月分区
优化器hints的优化
当遇到SQL执行计划不好的情况,应优先考虑统计信息等问题,而不是直接加Hint了事。如果统计信息无误,应该考虑物理结构是否合理,即没有合适的索引。只有在最后仍然不能SQL按优化的执行计划执行时,才考虑Hint。
Hint的弊端
-
Hint是比较"暴力"的一种解决方式,不是很优雅。需要开发人员手工修改代码。
-
Hint不会去适应新的变化。比如数据结构、数据规模发生了重大变化,但使用Hint的语句是感知变化并产生更优的执行计划。
-
Hint随着数据库版本的变化,可能会有一些差异、甚至废弃的情况。此时,语句本身是无感知的,必须人工测试并修正