mysql partition 实战

一般情况下我们创建的表对应一组存储文件,使用MyISAM存储引擎时是一个.MYI.MYD文件,使用Innodb存储引擎时是一个.ibd.frm(表结构)文件。当数据量较大时(一般千万条记录级别以上),MySQL的性能就会开始下降,这时我们就需要将数据分散到多组存储文件,保证其单个文件的执行效率。读写分离分散数据库读写操作压力,分库分表分散存储压力。

目录

1. hash(field)

2. key(field)

3. range(field)

4. list(field)

5. 分区管理

5.1 key/hash

5.2 range/list

6. 分区的使用


最常见的分区方案是按id分区,如下将id的哈希值对10取模将数据均匀分散到10个.ibd存储文件中:

create table article(
	id int auto_increment PRIMARY KEY,
	title varchar(64),
	content text
)PARTITION by HASH(id) PARTITIONS 10

物理存储data目录:

MySQL提供的分区算法

1. hash(field)

  • 相同的输入得到相同的输出
  • 适用于整型字段。

2. key(field)

hash(field)的性质一样,只不过key处理字符串的,比hash()多了一步从字符串中计算出一个整型在做取模操作。

create table article_key(
	id int auto_increment,
	title varchar(64),
	content text,
	PRIMARY KEY (id,title)	-- 要求分区依据字段必须是主键的一部分
)PARTITION by KEY(title) PARTITIONS 10

3. range(field)

  • 条件分区算法
  • 按照数据大小范围分区(将数据使用某种条件,分散到不同的分区中)
  • 条件运算符(less than)
create table article_range(
	id int auto_increment,
	title varchar(64),
	content text,
	created_time int,	-- 发布时间到1970-1-1的毫秒数
	PRIMARY KEY (id,created_time)	-- 要求分区依据字段必须是主键的一部分
)charset=utf8
PARTITION BY RANGE(created_time)(-- 注意:分区的定义顺序依照created_time数值范围从小到大,不能颠倒
	PARTITION p201808 VALUES less than (1535731199),	-- select UNIX_TIMESTAMP('2018-8-31 23:59:59')
	PARTITION p201809 VALUES less than (1538323199),	-- 2018-9-30 23:59:59
	PARTITION p201810 VALUES less than (1541001599)	-- 2018-10-31 23:59:59
);

4. list(field)

  • 条件分区算法
  • 按照列表值分区(in (值列表)
create table article_list(
	id int auto_increment,
	title varchar(64),
	content text,
	status TINYINT(1),	-- 文章状态:0-草稿,1-完成但未发布,2-已发布
	PRIMARY KEY (id,status)	-- 要求分区依据字段必须是主键的一部分
)charset=utf8
PARTITION BY list(status)(
	PARTITION writing values in(0,1),	-- 未发布的放在一个分区	
	PARTITION published values in (2)	-- 已发布的放在一个分区
);

5. 分区管理

如何查看某个表的所有分区?

show create table stat

5.1 key/hash

-- 增加分区
-- 尝试使用range对文章按照月份归档,随着时间的增加,我们需要增加一个月份
alter table article_range add partition(
	partition p201811 values less than (1543593599)	-- select UNIX_TIMESTAMP('2018-11-30 23:59:59')
	-- more
);
-- 删除分区
alter table article_range drop PARTITION p201808

注意:删除分区后,分区中原有的数据也会随之删除!

5.2 range/list

key/hash分区的管理不会删除数据,但是每一次调整(新增或删除分区)都会将所有的数据重写分配到新的分区上。效率极低,最好在设计阶段就考虑好分区策略。

-- 新增分区(在原理的基础上新增)
alter table article_key add partition partitions 4
-- 删除分区
alter table article_key coalesce partition 6

-- 也可以按日期
ALTER TABLE stat
    PARTITION BY RANGE(TO_DAYS(dt)) (
        PARTITION p0 VALUES LESS THAN(0),
        PARTITION p190214 VALUES LESS THAN(TO_DAYS('2019-02-14')),
        PARTITION pm VALUES LESS THAN(MAXVALUE)
    );
-- 如何进行动态扩容?
-- 增加分区需要用到 REORGANIZE 命令,它的作用是对某个分区重新分配。 比如明天是 15 号,那我们要给 15 号也增加个分区,实际上就是把 pm 分区拆分成2个分区:
ALTER TABLE stat
    REORGANIZE PARTITION pm INTO (
        PARTITION p190215 VALUES LESS THAN(TO_DAYS('2019-02-15')),
        PARTITION pm VALUES LESS THAN(MAXVALUE)
    );

6. 分区的使用

  • 当数据表中的数据量很大时,分区带来的效率提升才会显现出来
  • 只有检索字段为分区字段时,分区带来的效率提升才会比较明显
  • 分区字段的选择很重要(业务逻辑要尽可能地使用分区字段作为查询条件)

分区有利于管理非常大的表,它采用分而治之的逻辑。

### MySQL性能优化实战技巧与最佳实践 #### 配置调优 在MySQL性能优化中,合理调整配置文件`my.cnf`中的参数至关重要。对于InnoDB存储引擎的核心参数,建议如下设置: - `innodb_buffer_pool_size`: 设置为物理内存的70%-80%,用于缓存数据和索引,减少磁盘I/O开销[^1]。 - `innodb_log_file_size`: 对于大事务场景,适当增大该值可以提升性能,推荐设置为2GB或更高[^2]。 - `innodb_flush_log_at_trx_commit`: 默认值为1(每次提交都会写入磁盘),可将其设为2以平衡安全性和性能。 此外,针对连接管理部分,可以通过以下方式优化: - 使用`SHOW STATUS LIKE 'Threads_connected';`查看当前连接数状态。 - 调整`max_connections`至适合业务需求的最大值(如2000)。 - 减少空闲连接占用资源,通过设置`wait_timeout=300`来实现自动断开长时间未使用的连接。 #### 查询缓存机制 开启并利用好查询缓存也是提高MySQL性能的有效手段之一。如果应用中有大量重复执行且结果集不变的SQL语句,则应充分利用这一特性。需要注意的是,在频繁修改的数据表上启用查询缓存可能会适得其反,因为任何变更都将导致整个缓存失效[^3]。 #### 数据分布策略 为了进一步改善大规模数据环境下的读取效率,可以考虑采用基于哈希算法分区的方式进行水平拆分。例如按照用户ID计算hash值后分配到不同分片中(user_0 ~ user_7),从而达到负载均衡的目的。 ```sql CREATE TABLE users ( id INT NOT NULL, name VARCHAR(50), PRIMARY KEY (id) ) PARTITION BY HASH(id) PARTITIONS 8; ``` 以上就是关于MySQL性能优化的一些实际操作方法以及最佳实践经验总结。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值