zoukankan      html  css  js  c++  java
  • MySQL Execution Plan--合理利用隐式的业务逻辑

    问题描述

    优化过程中遇到一个SQL:

    SELECT
    SUM(user_value)
    FROM user_log
    WHERE del_flag = 0
    AND product_id = 2324
    AND user_type = 1;

    其执行计划为:

    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: user_log
       partitions: NULL
             type: ref
    possible_keys: index_sId_ty_vl_ct,IDX_product_id_oth1
              key: IDX_product_id_oth1
          key_len: 12
              ref: const,const,const
             rows: 14884
         filtered: 100.00
            Extra: Using index
    1 row in set, 1 warning (0.00 sec

    从执行计划来看,使用Using index(覆盖索引)已经是最优的执行计划,但每次查询扫描数据较多,影响整体查询性能。

    优化方案

    查询需要使用SUM计算user_value的总和,借用1+1+0+0+0+0+0=1+1=2的例子,进行如下测试:

    SELECT
    SUM(CASE WHEN user_value>0 THEN 1 ELSE 0 END) AS count1,
    COUNT(1) AS count2
    FROM user_log
    WHERE del_flag = 0
    AND product_id = 2324
    AND user_type = 1;
    
    +--------+--------+
    | count1 | count2 |
    +--------+--------+
    |    680 |   8067 |
    +--------+--------+

    在假设user_value没有负值的情况下,下面两条SQL的结果相同:

    ##测试SQL1
    SELECT
    SUM(user_value),
    COUNT(1) AS count2
    FROM user_log
    WHERE del_flag = 0
    AND product_id = 2324
    AND user_type = 1;
    
    ##测试SQL2
    SELECT
    SUM(user_value)
    FROM user_log
    WHERE del_flag = 0
    AND product_id = 2324
    AND user_type = 1
    AND user_value>0;

    测试SQL1的执行时间为0.00327250,其资源消耗为:

    +----------------------+----------+----------+------------+--------------+---------------+-------+
    | Status               | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out | Swaps |
    +----------------------+----------+----------+------------+--------------+---------------+-------+
    | starting             | 0.000066 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | checking permissions | 0.000012 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | Opening tables       | 0.000016 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | init                 | 0.000021 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | System lock          | 0.000015 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | optimizing           | 0.000016 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | statistics           | 0.000127 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | preparing            | 0.000019 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | executing            | 0.000011 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | Sending data         | 0.002867 | 0.002999 |   0.000000 |            0 |             0 |     0 |
    | end                  | 0.000012 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | query end            | 0.000013 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | closing tables       | 0.000012 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | freeing items        | 0.000054 | 0.000000 |   0.000000 |            0 |             8 |     0 |
    | cleaning up          | 0.000012 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    +----------------------+----------+----------+------------+--------------+---------------+-------+

    而测试SQL2的执行时间为0.00072325,其资源消耗为:

    +----------------------+----------+----------+------------+--------------+---------------+-------+
    | Status               | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out | Swaps |
    +----------------------+----------+----------+------------+--------------+---------------+-------+
    | starting             | 0.000072 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | checking permissions | 0.000013 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | Opening tables       | 0.000016 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | init                 | 0.000021 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | System lock          | 0.000014 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | optimizing           | 0.000020 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | statistics           | 0.000089 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | preparing            | 0.000020 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | executing            | 0.000011 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | Sending data         | 0.000365 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | end                  | 0.000012 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | query end            | 0.000014 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | closing tables       | 0.000012 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | freeing items        | 0.000035 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    | cleaning up          | 0.000012 | 0.000000 |   0.000000 |            0 |             0 |     0 |
    +----------------------+----------+----------+------------+--------------+---------------+-------+

    在Sending data部分,两者在Durion部分差距约10倍,而测试SQL2在CPU_user部分差距更明显。

    总结:

    DBA在优化SQL时,除了从数据分布/索引结构等方面入手外,还需要从业务逻辑方面入手。

    PS:上面的优化是假设user_value没有负值,而实际业务逻辑中user_value可能存在负值,因此以上优化纯属于瞎编。

  • 相关阅读:
    nao机器人使用手册
    突然感觉简单的东西是最美的
    window10教育版激活失败
    linux新分区无法新建文件夹
    看看CSDN的吃相
    游戏mod启动器原理
    显示器选购指南
    维修老电视
    快乐小丑
    这猫会关水龙头,所以你只要给猫猫打开就行——华中师范大学的胖猫
  • 原文地址:https://www.cnblogs.com/gaogao67/p/11654649.html
Copyright © 2011-2022 走看看