首页 > 数据库 >mysql通过表分区来增加数据查询效率

mysql通过表分区来增加数据查询效率

时间:2023-06-29 18:04:45浏览次数:66  
标签:LESS 分区 PARTITION 查询 utf8mb4 VALUES mysql THAN

背景

我们mysql是单机, 其中有几个表体积会很大, 需要做分表来增加查询效率.
我们的数据是连续不断入库的,查询条件是一个批次一个批次的查,也可以看做是按时间段查询.

思路

  1. mysql事件Event:到一定时间把原表改名, 加一个后缀,比如user表改为user_1
    RENAME TABLE division_stop_data_1 TO division_stop_data;
    然后再重新创建原表同名同结构的空表

  2. mycat的 方式: 需要一个mycat中间件服务, 通过修改mycat的路由规则,拦截解析修改sql语句达到访问不同子表的效果.
    参考:https://blog.csdn.net/qq_33709508/article/details/120728498

  3. mysql的表分区: 将表按照某个列(分区键)的值建立多个分区(子表),查询时, 如果查询条件涉及分区键,则会只查询对应分区内的数据,避免全表扫描.
    参考1:https://www.cnblogs.com/yeyuzhuanjia/p/16149744.html
    参考2:https://blog.csdn.net/wrh_csdn/article/details/80019171

对比可行性

  1. 自动归档
    第一种方法看似简单但是有一个致命问题, 在创建新表和归档旧表时, 同一批次的数据可能会被分割到两个表中, 原查询语句无法满足这种查询. 并且在查询旧表数据时,表名变了, 也不能满足. 需要配合mycat,把旧表配置到mycat中作为子表
  2. 使用mycat有几个问题:
    a. 需要单独引入一个mycat中间件, 增加了运维成本,
    b. 并且mycat的schema文件中,为逻辑表配置子表时,子表不能使用通配符,必须指定确定的子表名称.此时必须提前创建好所有子表.可扩展性差
    image
    c. mycat配置完成后,原表的数据要分配到子表中需要自行按照分表策略把原表中的数据分别迁移到子表中.这个就很麻烦了
  3. 表分区
    MySQL在5.1时添加了对水平分区的支持。分区是将一个表或索引分解成多个更小,更可管理的部分。每个区都是独立的,可以独立处理,也可以作为一个更大对象的一部分进行处理。这个是MySQL支持的功能,业务代码无需改动。
    a.可以对已存在数据的表进行分区,且分区后数据会自动按分区规则进入相应的子表.
    b.无需增加中间件或是第三方插件

解决问题过程

本着改动最小,最符合我们的需求(单库水平分表)决定选择对几张大表进行表分区.

  1. 表分区前提
    mysql5.1后支持表分区

  2. 表分区类型
    MySQL支持的分区类型一共有四种:RANGELISTHASHKEY
    其中,
    RANGE又可分为原生RANGERANGE COLUMNS
    LIST分为原生LISTLIST COLUMNS
    HASH分为原生HASHLINEAR HASH
    KEY包含原生KEYLINEAR HASH
    image
    分析: 因为我们是按照批次号来查询数据,批次号是datetime + '_' + 随机数组成的字符串,差不多还是按照时间递增的.于是我们想以时间为依据,半年的数据分一个表, 所以我们应该选用range columns分区类型. range columns是基于range在mysql5.5以后新增的分区类型.
    区别:range类型分区的分区依据(分区键)必须是int类型的列或者表达式, 而range columns则可以是除了blob和text以外类型的列,但不能是表达式.
    注意:
    a. 分区键必须是查询时要用到的条件列,否则查询还是全表扫描,不会提高查询效率.
    b. 分区键必须要么是主键要么是联合主键的一部分
    ALTER TABLE continue_data ADD PRIMARY KEY (id, batch_no);
    c. range colums分区键不能是表达式
    d. range colums分区键可以接受多个字段

  3. 分区语法
    对于已有的表,按照半年一个分区,修改语法

ALTER TABLE continue_data_1 PARTITION BY RANGE COLUMNS(batch_no) (
  PARTITION p0 VALUES LESS THAN ('202006'),
	PARTITION p1 VALUES LESS THAN ('202012'),
  PARTITION p2 VALUES LESS THAN ('202106'),
	PARTITION p3 VALUES LESS THAN ('202112'),
  PARTITION p4 VALUES LESS THAN ('202206'),
	PARTITION p5 VALUES LESS THAN ('202212'),
  PARTITION p6 VALUES LESS THAN ('202306'),
	PARTITION p7 VALUES LESS THAN ('202312'),
  PARTITION p8 VALUES LESS THAN MAXVALUE
);

对于新创建的表,直接在后面加partition by即可

CREATE TABLE `continue_data_1` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
  `cab_no` int DEFAULT NULL COMMENT '柜号',
  `cell_no` int DEFAULT NULL COMMENT '库号',
  `channel_no` int DEFAULT NULL COMMENT '通道号',
  `battery_no` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '电芯码',
  `tray_no` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '托盘码',
  `batch_no` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '批次号',
  `recipe_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '配方名',
  `func_code` int DEFAULT NULL COMMENT '功能码',
  `data` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '续接内容',
  `create_timestamp` datetime DEFAULT NULL,
  `update_timestamp` datetime DEFAULT NULL,
  PRIMARY KEY (`id`,`batch_no`)
) ENGINE=InnoDB AUTO_INCREMENT=101416 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
 PARTITION BY RANGE  COLUMNS(batch_no)
(PARTITION p0 VALUES LESS THAN ('202006') ENGINE = InnoDB,
 PARTITION p1 VALUES LESS THAN ('202106') ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN ('202206') ENGINE = InnoDB,
 PARTITION p3 VALUES LESS THAN ('202306') ENGINE = InnoDB,
 PARTITION p4 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) 

测试

  1. 插入数据
//插入数据
delimiter $$
drop procedure if exists addBatchData;
CREATE PROCEDURE addBatchData()
BEGIN
    DECLARE num INT;
    SET num = 20200101;
    
    WHILE num <= 20301231 DO
        INSERT INTO continue_data_1 (batch_no, create_timestamp, update_timestamp) 
        VALUES (CONCAT(num, '000000_111'), NOW(), NOW());
        SET num = num + 1;
    END WHILE;
    
END$$;
delimiter;

call addBatchData();
  1. 查询一个指定批次号的数据,看看是否会避免全表扫描而直接去查那条数据所在的分区
explain SELECT * FROM continue_data_1 where batch_no = '20220102000000_111';

image

标签:LESS,分区,PARTITION,查询,utf8mb4,VALUES,mysql,THAN
From: https://www.cnblogs.com/qds1401744017/p/17514771.html

相关文章

  • MySQL 8.0.33 my.ini说明
    #其他默认调整值#MySQLServer实例配置文件#-------------------------------------------------------------------------------------------------------------------------------------------------------------#由MySQLServer实例配置向导生成###安装说明#------------......
  • Mybatis中查询出来的部分数据为空,能查出行部分字段为空
    同样的sql语句,在数据库中能查出完整的行数据在mybatis中返回数据中能查出行,但是部分有值的字段为空。首先检查缓存,没问题的话大概率是因为mybatis自动映射的关系:1.列名不匹配:自动映射会根据数据库中的列名和对象属性名进行映射,如果列名和属性名不匹配,就会导致数据为空。确保数......
  • Flutter私服搭建之package查询
    温馨提示:这是一篇私有的package客户端查询的平台搭建文章,牵扯到python中的Django框架,虽和Flutter相关,但客户端的代码并没有关联,请您根据需要进行阅读。公有的package,对于一个Flutter开发者而言,再熟悉不过,比如常见的网络库dio,存储库shared_preferences等等,我们都可以在官网进行查找......
  • mysql: [Warning] Using a password on the command line interface can be insecure.
      https://zhuanlan.zhihu.com/p/542166965 ......
  • 自由软件基金会为甲骨文支招 放弃MySQL
    本文发表于2009-10-2608:3911/2/200911:45:39AM据国外媒体报道,自由软件基金会欧洲分会(以下简称FSFE)周五表示,甲骨文应该将MySQL数据库交给一家独立的非营利机构,以便让欧盟尽早批准甲骨文收购Sun交易。FSFE称,甲骨文应该将MySQL数据库交给一家独立的非营利机构打理,这家机构要把......
  • 光脚丫学LINQ(005):数据表之间的联接查询
      视频演示:http://u.115.com/file/f29a440f67 联接运算创建数据源中没有显式建模的序列之间的关联。例如,您可以执行联接来查找符合以下条件的所有客户:位于巴黎,且从位于伦敦的供应商处订购产品。在LINQ中,join子句始终针对对象集合而非直接针对数据库表运行。在LINQ中,您不必......
  • Mysql十题
    181.超过经理收入的员工SQL架构表:Employee +-------------+---------+|ColumnName|Type|+-------------+---------+|id|int||name|varchar||salary|int||managerId|int|+-------------+---------+Id......
  • SQL Server查询重复数据
    1.查询单列重复select*fromtablewherenamein(selectnamefromtablegroupbynamehavingcount(name)>1)2.查询多列重复SELECTa.*FROMtablea,(SELECTname,codeFROMtableGROUPBYname,codeHAVINGCOUNT(1)>1)ASbWHEREa.name=b.nameANDa.......
  • Mysql必备技能点
    一、SQL顺序1.sql语句执行顺序:from-->where-->groupby-->having-->select--->orderby;我们先执行from,join来确定表之间的连接关系,得到初步的数据where对数据进行普通的初步的筛选groupby分组各组分别执行having中的普通筛选或者聚合函数筛选。然后把再根据我们要......
  • Android system & system_ext & product等分区中的build.prop文件是怎么生成的?
    Androidsystem&system_ext&product等分区中的build.prop文件是怎么生成的? #http://aospxref.com/android-13.0.0_r3/xref/build/make/core/sysprop.mk #http://aospxref.com/android-13.0.0_r3/xref/build/make/tools/buildinfo.sh buildinfo.sh脚本内容:#!/bin......