美文网首页
数据库表优化转载

数据库表优化转载

作者: geeooooz | 来源:发表于2022-05-18 14:24 被阅读0次

    转载:https://zhuanlan.zhihu.com/p/214377808

    比如:

    有一张财务流水表,未分库分表,目前的数据量为9555695,分页查询使用到了limit,优化之前的查询耗时16 s 938 ms (execution: 16 s 831 ms, fetching: 107 ms),按照下文的方式调整SQL后,耗时347 ms (execution: 163 ms, fetching: 184 ms);

    操作:查询条件放到子查询中,子查询只查主键ID,然后使用子查询中确定的主键关联查询其他的属性字段;

    原理:减少回表操作;

    -- 优化前SQL
    SELECT  各种字段
    FROM `table_name`
    WHERE 各种条件
    LIMIT 0,10;
    
    
    -- 优化后SQL
    SELECT  各种字段
    FROM `table_name` main_tale
    RIGHT JOIN 
    (
    SELECT  子查询只查主键
    FROM `table_name`
    WHERE 各种条件
    LIMIT 0,10;
    ) temp_table ON temp_table.主键 = main_table.主键
    

    一,前言
    首先说明一下MySQL的版本:

    mysql> select version();
    +-----------+
    | version() |
    +-----------+
    | 5.7.17    |
    +-----------+
    1 row in set (0.00 sec)
    表结构:
    
    mysql> desc test;
    +--------+---------------------+------+-----+---------+----------------+
    | Field  | Type                | Null | Key | Default | Extra          |
    +--------+---------------------+------+-----+---------+----------------+
    | id     | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
    | val    | int(10) unsigned    | NO   | MUL | 0       |                |
    | source | int(10) unsigned    | NO   |     | 0       |                |
    +--------+---------------------+------+-----+---------+----------------+
    3 rows in set (0.00 sec)
    

    id为自增主键,val为非唯一索引。

    灌入大量数据,共500万:

    mysql> select count(*) from test;
    +----------+
    | count(*) |
    +----------+
    |  5242882 |
    +----------+
    1 row in set (4.25 sec)
    

    我们知道,当limit offset rows中的offset很大时,会出现效率问题:

    mysql> select * from test where val=4 limit 300000,5;
    +---------+-----+--------+
    | id      | val | source |
    +---------+-----+--------+
    | 3327622 |   4 |      4 |
    | 3327632 |   4 |      4 |
    | 3327642 |   4 |      4 |
    | 3327652 |   4 |      4 |
    | 3327662 |   4 |      4 |
    +---------+-----+--------+
    5 rows in set (15.98 sec)
    

    为了达到相同的目的,我们一般会改写成如下语句:

    mysql> select * from test a inner join (select id from test where val=4 limit 300000,5) b on a.id=b.id;
    +---------+-----+--------+---------+
    | id      | val | source | id      |
    +---------+-----+--------+---------+
    | 3327622 |   4 |      4 | 3327622 |
    | 3327632 |   4 |      4 | 3327632 |
    | 3327642 |   4 |      4 | 3327642 |
    | 3327652 |   4 |      4 | 3327652 |
    | 3327662 |   4 |      4 | 3327662 |
    +---------+-----+--------+---------+
    5 rows in set (0.38 sec)
    

    时间相差很明显。

    为什么会出现上面的结果?我们看一下select * from test where val=4 limit 300000,5;的查询过程:

    查询到索引叶子节点数据。

    根据叶子节点上的主键值去聚簇索引上查询需要的全部字段值。

    相关文章

      网友评论

          本文标题:数据库表优化转载

          本文链接:https://www.haomeiwen.com/subject/oaraurtx.html