• 记一次MySQL表分区操作


    最近一次日常迭代中,业务线需要对一张大表进行联合查询,查询性能可想而知,测试过程中服务接口直接响应超时,导致服务不可用,最后临时对该表进行分区操作,暂时缓解性能问题。由于是第一次操作表分区,姑且记录一下整个操作过程。

    测试表结构

    1
    2
    3
    4
    5
    6
    7
    8
    CREATE TABLE `tb_partition_test` (
    `user_id` bigint(20) NOT NULL ,
    `city_id` bigint(20) NOT NULL DEFAULT '0',
    `record_type` smallint(6) NOT NULL DEFAULT '0',
    `record` smallint(6) NOT NULL DEFAULT '0' ,
    `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (`user_id`,`record_type`),
    ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='分区测试';

    表应用场景为:存储用户的成绩明细数据,成绩计算有多种不同的维度,每个用户的每个成绩维度只有一个分值。所以整个表按照record_type分组后,每个成绩对应的数据量是一致的,都为用户数量。最后对record_type进行hash分区。

    为了不影响生产环境的业务使用,而恰好该表又不会有业务更新操作,故新建一个分区表,将原有表数据导入,采取分块导入的方式,避免产生大量的临时文件。

    创建分区表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CREATE TABLE `tb_partition_test_part` (
    `user_id` bigint(20) NOT NULL ,
    `city_id` bigint(20) NOT NULL DEFAULT '0',
    `record_type` smallint(6) NOT NULL DEFAULT '0',
    `record` smallint(6) NOT NULL DEFAULT '0' ,
    `create_time` timestamp NOT NULL DEFAULT 大专栏  记一次MySQL表分区操作 CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (`user_id`,`record_type`),
    ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='分区测试'
    PARTITION BY HASH(record_type)
    PARTITIONS 100;

    数据导入

    1
    2
    3
    4
    5
    for i in {1..100};do
    "INSERT IGNORE INTO tb_partition_test_part
    SELECT * from tb_partition_test WHERE score_type=$i;"
    sleep 5
    done

    导入完成后修改表名,会有短暂时间的锁表

    1
    2
    3
    4
    5
    6
    set AUTOCOMMIT = 0;
    BEGIN ;
    RENAME TABLE tb_partition_test to tb_partition_test_20170916;
    RENAME TABLE tb_partition_test_part to tb_partition_test;
    COMMIT ;
    set AUTOCOMMIT = 1;

    查询性能比较:

    通过explain partitions查看执行计划,对于指定record_type的查询,只会在指定的分区中查找,数据按照record_type均匀分区了,前后执行时间比较

    1
    2
    3
    4
    5
    6
    +----------+
    | count(0) |
    +----------+
    | 361795 |
    +----------+
    1 row in set (42.89 sec)
    1
    2
    3
    4
    5
    6
    +----------+
    | count(0) |
    +----------+
    | 361795 |
    +----------+
    1 row in set (3.04 sec)

    显然3.04 sec的性能仍是不可接受的,作为相对低频的业务,这只是临时的处理方案,而且恰好因为目前的需求在每次查询都会附带record_type条件,所以可以很好的利用分区提升性能,但如果出现不按照record_type条件的查询,仍然会出现性能瓶颈,需要后端人员以及来进行优化。

    参考

      1. https://dev.mysql.com/doc/refman/5.6/en/partitioning-hash.html
      2. http://www.cnblogs.com/chenmh/p/5623474.html
      3. http://blog.csdn.net/zzy7075/article/details/70054818
      4.http://blog.csdn.net/yongchao940/article/details/55266603

  • 相关阅读:
    G
    C
    B
    B
    线段树模板
    网络流模板
    POJ_1631_Bridging_Signals_(动态规划,LIS)
    POJ_1065_Wooden_Sticks_(动态规划,LIS+鸽笼原理)
    BZOJ_1015_星球大战_[JSOI2008]_(并查集)
    POJ_3280_Cheapest_Palindrome_(动态规划)
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12255925.html
Copyright © 2020-2023  润新知