zoukankan      html  css  js  c++  java
  • SQL调优

    背景

        每当交易高峰时期,可能会暴露一些平时无法发现的问题,机遇和挑战并存。下面聊聊最近解决的一个案例,因为执行计划走错导致慢查询,进而引发应用线程阻塞、线程池爆满,最后应用功能瘫痪。如何标本兼治的解决问题,需要很多思考。

    问题分析

       step1 应用瘫痪

        用户反应某查询功能一直处于加载中,并出现错误提示。查看后台应用日志,调用远程查询服务出现大量超时。

       step2 线程池爆满

        通过jstack命令来分析查询服务jvm线程堆栈,发现设定的线程池已经满了,而且大部分线程阻塞在了数据库查询阶段(如下图),看来是有很多慢查询。

    step3 慢查询的由来 - 错误执行计划

    为何忽然出现这么多慢查询?我们来分析一下:

    1. SELECT no, time
    2. FROM tablename
    3. where no = :1
    4. and time >= to_date(:2, 'yyyy-mm-dd')
    5. and time < to_date(:3, 'yyyy-mm-dd')
    6. ORDER BY time DESC

    注:条件字段(no、time)分别有索引(idx_no、idx_time)。

    经过DBA帮助,分析上段sql的执行计划发现:

    • 有时数据库会走idx_no索引,查询很快

    • 有时会走idx_time索引,查询很慢

     

    解决方案

        既然数据库自动生成的执行计划有时会出问题,那么我们可以用hints语句指定当前sql走哪条索引,以固定执行计划。

    下面以Oracle为例,添加hints:

    1. SELECT /*+ index(tablename IDX_NO) */ no, time
    2. FROM tablename
    3. where no = :1
    4. and time >= to_date(:2, 'yyyy-mm-dd')
    5. and time < to_date(:3, 'yyyy-mm-dd')
    6. ORDER BY time DESC

    如果感觉在sql中添加不方便的话,oracle 10g以上版本提供了SQL Profile方式。

    总结思考

        这个问题应该一直有,为何在交易高峰时段才表现出来值得去研究。

        数据库:平时数据库压力较小,出现几个走错执行计划的慢查询,也只是让数据库压力比均值高出一小部分,性能未受影响。但是,高峰时段数据库本身就处于一个高负载状态,这时出现的慢查询无疑是雪上加霜,接近某个临界点时性能就明显下滑。

        应用:慢查询会导致线程阻塞等待,一直占用线程池资源。我们知道,用户在点击查询按钮后发现一直加载,会不知觉多点几遍。这样的话,线程数量暴涨且大部分处于阻塞状态,线程池满了之后应用就会瘫痪掉,使其他正常的接口也无法正常工作。

        综上所述,数据层的优化是治本,同时还要借助一些手段来保证不出现雪崩式性能下降。比如,在前台页面添加重复提交限制,尽量避免短时间内产生大量慢查询。

    参考资料

    Oracle Hints:https://docs.oracle.com/cd/B12037_01/server.101/b10752/hintsref.htm#5156

    Oracle SQL Profile:https://docs.oracle.com/database/121/TGSQL/tgsql_profiles.htm#TGSQL596

  • 相关阅读:
    Nginx练习练习玩玩
    MySQL Lock--MySQL加锁规则
    MySQL Transaction--RR事务隔离级别下加锁测试
    MySQL Transaction--RC事务隔离级别下加锁测试
    MySQL Transaction--事务隔离级别基础
    MySQL Transaction--快照读和当前读
    MySQL Transaction--RC和RR区别
    MySQL Disk--NAND Flash原理
    MySQL Disk--SSD与RAID
    MySQL Disk--SSD磁盘性能抖动问题
  • 原文地址:https://www.cnblogs.com/feiqihang/p/5310517.html
Copyright © 2011-2022 走看看