mysql里的range分区方式和主键冲突了怎么办?innodb中没有主键会造成啥影响?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql里的range分区方式和主键冲突了怎么办?innodb中没有主键会造成啥影响?相关的知识,希望对你有一定的参考价值。

目前有个5000W条的订单表,数据长度在30G左右,索引长度好像也有15G,已经出现聚合函数查询缓慢.
从网上资料找了些原因.应该是索引过大.缓存使用不过来了.
所以想根据订单的创建时间来做分区表以减小索引消耗.
于是就遇见了分区与主键冲突的问题.最终我们使用了hash主键列方式的分区.但实际环境中运行了一段时间后发现这种方式并不理想.mysql进程消耗更加高了.而且也没有改善查询问题.
本地测试过发现分区字段外不能存在具有唯一约束的列.
现在我们改造方案纠结于是否移除主键.我们这边表使用innodb引擎,网上资料提到innodb是B-树这种结构,主键对于其好像有特殊意义,没有主键后会带来的影响我们目前也不甚了解.想咨询一下没有主键在什么场景会有棘手的问题.
另外求个mysql交流群或聚集地......目前学习数据库维护好无力.

innodb如果没有索引,默认会有一个隐藏的聚集索引Rowid的。

主要取决于你的商业逻辑,

个人观点:铲除掉那个主键不会对索innodb造成影响,如果用了隐藏索引,可以考虑适当增大分区,尽量保持顺序写入,还会适当提高效率的追问

早上加入了1楼提供的群和人聊了聊,了解了些关于innodb的主键的相关资料。
目前没有这方面的基础,只能猜测着弄。已测的结果是当表中没有主键与唯一索引列时,range分区才能添加进去。
现在面临的麻烦就是在业务逻辑内有使用到on duplicate key update做批量插入时的重复数据更新,没有主键的话就得改造。目前没有能替代这种更新的方案,请问有没有不依赖唯一约束的插入更新方式?

追答

按照你目前的情况,我觉得可行方案

每次插入的时候做一个primary key checking, 也就是检查你的主建字段是否已经存在,如果存在,不能插入。

把数据库应该做的duplicate key checking by primary key转化为我们自己的checking.

来自:求助得到的回答
参考技术A 群号134787534

记录一下MySQL的表分区常用操作

一、分区条件

  1. 一个表最多只能有1024个分区。
  2. MySQL5.1之后,才支持表分区功能,且分区表达式必须是整数。
  3. MySQL5.5之后,增加了COLUMNS分区(RANGE / LIST),支持整形、日期、字符串。
  4. 分区字段,必须包含在主键字段内。

二、预处理主键

目的:将分区字段添加到主键

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)
);

八、分区的应用

  1. 按分区检索
    SELECT * FROM tb_article PARTITION(pEast);
    SELECT atc.* 
    FROM tb_article PARTITION(pEast) atc
    INNER JOIN tb_region rg ON rg.region = atc.region;

     

  2. 删除分区内的数据
    DELETE FROM tb_artical PARTITION(pEast)

     

  3. 修改分区内的数据
    UPDATE tb_artical PARTITION(pEast)
    SET title = CONCAT(title,  - modify)
    WHERE id = xxx001;

     

以上是关于mysql里的range分区方式和主键冲突了怎么办?innodb中没有主键会造成啥影响?的主要内容,如果未能解决你的问题,请参考以下文章

记录一下MySQL的表分区常用操作

十、MySQL表分区

MySQL 分区表,为啥分区键必须是主键的一部分?

通过dbeaver创建mysql表时,如何设置主键和主键自增。不适用sql语句,仅通过dbeaver可视化操作来创建。

Mysql --- 分区表

MySQL表分区优势及分类简析 MySQL DBA学习