mysql里的range分区方式和主键冲突了怎么办?innodb中没有主键会造成啥影响?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql里的range分区方式和主键冲突了怎么办?innodb中没有主键会造成啥影响?相关的知识,希望对你有一定的参考价值。
目前有个5000W条的订单表,数据长度在30G左右,索引长度好像也有15G,已经出现聚合函数查询缓慢.
从网上资料找了些原因.应该是索引过大.缓存使用不过来了.
所以想根据订单的创建时间来做分区表以减小索引消耗.
于是就遇见了分区与主键冲突的问题.最终我们使用了hash主键列方式的分区.但实际环境中运行了一段时间后发现这种方式并不理想.mysql进程消耗更加高了.而且也没有改善查询问题.
本地测试过发现分区字段外不能存在具有唯一约束的列.
现在我们改造方案纠结于是否移除主键.我们这边表使用innodb引擎,网上资料提到innodb是B-树这种结构,主键对于其好像有特殊意义,没有主键后会带来的影响我们目前也不甚了解.想咨询一下没有主键在什么场景会有棘手的问题.
另外求个mysql交流群或聚集地......目前学习数据库维护好无力.
主要取决于你的商业逻辑,
个人观点:铲除掉那个主键不会对索innodb造成影响,如果用了隐藏索引,可以考虑适当增大分区,尽量保持顺序写入,还会适当提高效率的追问
早上加入了1楼提供的群和人聊了聊,了解了些关于innodb的主键的相关资料。
目前没有这方面的基础,只能猜测着弄。已测的结果是当表中没有主键与唯一索引列时,range分区才能添加进去。
现在面临的麻烦就是在业务逻辑内有使用到on duplicate key update做批量插入时的重复数据更新,没有主键的话就得改造。目前没有能替代这种更新的方案,请问有没有不依赖唯一约束的插入更新方式?
按照你目前的情况,我觉得可行方案
每次插入的时候做一个primary key checking, 也就是检查你的主建字段是否已经存在,如果存在,不能插入。
把数据库应该做的duplicate key checking by primary key转化为我们自己的checking.
记录一下MySQL的表分区常用操作
一、分区条件
- 一个表最多只能有1024个分区。
- MySQL5.1之后,才支持表分区功能,且分区表达式必须是整数。
- MySQL5.5之后,增加了COLUMNS分区(RANGE / LIST),支持整形、日期、字符串。
- 分区字段,必须包含在主键字段内。
二、预处理主键
目的:将分区字段添加到主键
ALTER TABLE <表名> DROP PRIMARY KEY, ADD PRIMARY KEY (`id`, `<分区字段>`);
例如:
ALTER TABLE tb_article DROP PRIMARY KEY, ADD PRIMARY KEY (`id`, `cdate`);
三、创建分区
定义分区规则:
PARTITION BY [ RANGE | LIST ] COLUMNS(<分区字段>)( PARTITION <分区名> VALUES <分区规则>, ... )
可以在建表(CREATE TABLE)时直接创建分区:
CREATE TABLE `<表名>` ( `<ID字段名>` varchar(20) NOT NULL COMMENT ‘ID‘, `<分区字段名>` varchar(20) NOT NULL COMMENT ‘分区‘, ... , PRIMARY KEY (`<ID字段名>`, `<分区字段名>`) ) PARTITION BY [ RANGE | LIST ] COLUMNS(<分区字段>)( PARTITION <分区名> VALUES <分区规则>, ... );
也可以为现有表创建分区(ALTER TABLE),但需要提前将分区字段添加到主键。
ALTER TABLE `<表名>` PARTITION BY [ RANGE | LIST ] COLUMNS(<分区字段>)( PARTITION <分区名> VALUES <分区规则>, ... );
四、添加分区
ALTER TABLE `<表名>` ADD PARTITION ( PARTITION <分区名> VALUES <分区规则>, ... );
五、删除分区
同时也会删除分区内的数据
ALTER TABLE `<表名>` DROP PARTITION <分区名>;
六、实例1:创建 RANGE COLUMNS 分区
CREATE TABLE tb_article ( id VARCHAR(20) NOT NULL, title VARCHAR(50) NOT NULL, cdate DATE NOT NULL, PRIMARY KEY (id, cdate) ) PARTITION BY RANGE COLUMNS(cdate)( PARTITION p2018 values less than (‘2018‘), PARTITION p2019 values less than (‘2019‘), PARTITION p2020 values less than (MAXVALUE) );
七、实例2:创建 LIST COLUMNS 分区
CREATE TABLE tb_article ( id VARCHAR(20) NOT NULL, title VARCHAR(50) NOT NULL, region VARCHAR(20) NOT NULL, PRIMARY KEY (id, region) ) PARTITION BY LIST COLUMNS(region)( PARTITION pEast values in (‘east‘), PARTITION pWest values in (‘west‘), PARTITION pNorth values in (‘north‘), PARTITION pSouth values in (‘south‘) );
八、分区的应用
- 按分区检索
SELECT * FROM tb_article PARTITION(pEast);
SELECT atc.* FROM tb_article PARTITION(pEast) atc INNER JOIN tb_region rg ON rg.region = atc.region;
- 删除分区内的数据
DELETE FROM tb_artical PARTITION(pEast)
- 修改分区内的数据
UPDATE tb_artical PARTITION(pEast) SET title = CONCAT(title, ‘ - modify‘) WHERE id = ‘xxx001‘;
以上是关于mysql里的range分区方式和主键冲突了怎么办?innodb中没有主键会造成啥影响?的主要内容,如果未能解决你的问题,请参考以下文章