java-mysql优化历程

起因

web运行页面加载速度突然变慢,从5秒左右变为2~3分钟。

查找问题源头:

1:代码问题:

因为业务逻辑复杂,运行两段sql进行数据查询,根据第一段sql查出来的数id在第二段sql里进行in查询,但由于第一段sql查出的数据量大概有6W+,所以在拼接sql中字符串长度过长导致报错GC。

2:数据库问题:

因为业务逻辑变更,导致sql查询的其中一张表,从1~2w条数据四五天内增加至150W+,导致单表查询运行速度超过5s,关联查询至少要20s左右。

解决:

1:修改代码逻辑,通过获取小数据量的值对大的sql进行关联查询,减少java内存消耗。

其中有一段业务逻辑是要获取一棵树上根据树的多个节点,获取多个节点下的所有子节点,开始的想法是,根据java代码来实现,实现方式是:

  • 获取某个父节点下面的所有子节点
  /* 获取某个父节点下面的所有子节点
     * @param menuList
     * @param pid
     * @return
     */
    static List<String> childMenu = new ArrayList<>();
    public static List<String> treeMenuList(List<Map<String, Object>> menuList, String pid) {
        for (Map<String, Object> mu : menuList) {
            //遍历出父id等于参数的id,add进子节点集合
            if (pid.equals(String.valueOf(mu.get("parentid")))) {
                //递归遍历下一级
                treeMenuList(menuList, String.valueOf(mu.get("id")));
                childMenu.add(String.valueOf(mu.get("id")));
            }
        }
        return childMenu;
    }

但是这种方式仍然会使优化过mysql后的加载速度达到7~8秒,由于时间问题没有去管为什么会慢,但猜测是因为传入的List集合过大。
思考另外一种方案用mysql函数去处理这段逻辑,在一片文章中找到很好的例子:

SELECT * FROM person WHERE department IN
(SELECT department_id FROM department WHERE department_id = 20006
UNION
(SELECT department_id FROM
  (SELECT  * FROM department ORDER BY parent_id,department_id) depart_sorted,
  (SELECT @pv := 20006) initialisation
WHERE find_in_set(parent_id,@pv)
AND length(@pv := concat(@pv,',',department_id))));

生产库中测试运行速度秒级,已达标。

2:优化sql,创建索引

由于是数据量突然增加的问题导致的,首先想到的就是创建索引。
但是没想到,创建索引的时间超出我的想象,分别用了脚本,navicat,倒库等多中方式创建都不成功,开始想到的是因为数据量太大,在等待一个小时后发现还没有成功,知道事情没有这么简单,开始寻找出路。。。。。
是否有某个查询把表造成死锁;查询:

select trx_state, trx_started, trx_mysql_thread_id, trx_query from information_schema.innodb_trx;

查询后果然发现了一条有关建索引表的sql存在死锁,果断kill。

至此页面加载的速度已经从23分钟优化至23秒(其中包括一些sql语句的优化未写出);

才疏学浅,不喜勿喷。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章