云原生分布式数据库PolarDB-X_DRDS_分库分表_数据库-阿里云 (aliyun.com)是由阿里巴巴自主研发的云原生分布式数据库,具备水平扩容、金融级高可用、HTAP混合负载
、兼容 MySQL 等重要特性,专注解决超高并发吞吐、海量数据存储、大表瓶颈等数据库瓶颈难题,历经各届天猫双11及阿里云各行业客户业务的考验,助力企业加速完成业务数字化转型。分布式数据库PolarDB-X开源版 (polardbx.com)
适用场景
高负载低延时交易
大峰谷差流量
数据集中存储
分布式快速改造
数据库国产化替换
混合负载访问
名词解释
- 分区键:分区表中用于进行水平切分的一个列或多个列。
- 分区列:水平切分后,参与分区路由及计算的列,它通常是分区键的一部分,一个分区键可以含有一个或多个分区列。
- 向量分区键:由一个或多个分区列组成的分区键。
- 单列分区键:由一个分区列组成的分区键。
- 前缀分区列:若一个向量分区键由N(N>1)个分区列组成,它的前K(1<=K<=N)个分区列便组成这个向量分区键的前缀分区列。
- 分区函数:将分区列作为一个函数的输入参数,并将该函数的输出结果作为原始值参与路由计算,该函数被称为分区函数。
- 分区裁剪:根据
分区定义
及查询条件
,最大限度地过滤不需要扫描的分区的查询优化手段。 - 热点分裂:当向量分区键的前缀分区列存在访问热点或分布不均衡时,允许使用下一个分区列对热点分区进行分裂,以达到负载均衡效果【key(向量分区键)、range columns(向量分区键)支持】。
- 自动分区表:不指定
partition by
等相关参数 - 手动分区表:指定
partition by
等相关参数 - 回表
操作
数据库
AUTO模式数据库与DRDS模式数据库 (aliyun.com)
- 创建AUTO模式数据库必须在
CREATE DATABASE
语法中显式指定MODE='AUTO'
。 - 如果在
CREATE DATABASE
语法中不指定MODE参数的值,默认创建DRDS模式的数据库。 - AUTO模式数据库下不支持使用DRDS分库分表的语法创建表,仅支持创建分区表。
- DRDS模式数据库下不支持使用分区表的语法创建表,仅支持创建分库分表。
AUTO模式数据库
1 |
|
DRDS模式数据库
1 |
|
查看
1 |
|
表
分区表
auto模式下,默认创建分区表
CREATE TABLE `single_tbl` (
`id` int(11) NOT NULL,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
)
show full create table single_tbl;
CREATE PARTITION TABLE `single_tbl` (
`id` int(11) NOT NULL,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`id`)
PARTITIONS 24
/* tablegroup = `tg1` */
单表
不进行任何分区
如果一张表的数据,数据量预估在1000万条以下,且没有与其他拆分表进行关联查询的需求,建议将其设置为单表类型。
1 |
|
广播表
在所有DN节点上有一份数据完全相同的拷贝。
在业务数据库中,存在一些数据量不大,更新频度低,但常常需要用来做关联查询的表。
为了支持这类表与拆分表进行JOIN操作,可以采用广播表,具有以下特点:
- 广播表在各DN中数据一致。数据插入、更新与删除会实时在每一个DN中执行一次。
- 对广播表的查询,仅在一个DN中执行。
- 任何表都可以与广播表进行JOIN操作。
CREATE TABLE broadcast_tbl(
id bigint not null auto_increment,
bid int,
name varchar(30),
primary key(id)
) BROADCAST;
索引
本地索引(local index)
auto模式下,主键
默认会创建本地索引
CREATE TABLE auto_part(
id bigint not null auto_increment,
bid int,
name varchar(30),
primary key(id)
);
show full create table auto_part;
CREATE PARTITION TABLE `auto_part` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`bid` int(11) DEFAULT NULL,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`id`)
PARTITIONS 24
/* tablegroup = `tg6` */
查询本地索引
show index from auto_part;
1 |
|
单独创建本地索引
1 |
|
全局二级索引(global secondary index)
- 创建表的同时创建全局索引
CREATE TABLE t_order13 (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext DEFAULT NULL,
`order_detail` longtext DEFAULT NULL,
PRIMARY KEY (`id`),
GLOBAL index g_i_seller_id(`seller_id`) partition by hash(`seller_id`)
) partition by hash(`buyer_id`);
- 单独创建全局索引
CREATE GLOBAL INDEX `g_i_seller` ON t_order9 (`seller_id`) covering (`buyer_id`,`order_id`) partition by hash(`seller_id`) partitions 16;
- 当分区键为主键时(自动分区表),创建普通索引默认会同时创建全局索引
CREATE TABLE auto_part_tbl(
id bigint not null auto_increment,
bid int,
name varchar(30),
primary key(id),
index idx_name (name)
);
show full CREATE TABLE auto_part_tbl;
CREATE PARTITION TABLE `auto_part_tbl` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`bid` int(11) DEFAULT NULL,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
GLOBAL INDEX /* idx_name_$5159 */ `idx_name` (`name`) PARTITION BY KEY (`name`, `id`) PARTITIONS 24,
LOCAL KEY `_local_idx_name` (`name`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`id`)
PARTITIONS 24
/* tablegroup = `tg6` */
查询本地索引
show index from auto_part_tbl;
1 |
|
查询全局索引
show GLOBAL index from auto_part_tbl;
1 |
|
- 后创建普通索引,也会同时创建全局索引
CREATE TABLE auto_part_tbl4(
id bigint not null auto_increment,
bid int,
name varchar(30),
primary key(id)
);
create index i_name on auto_part_tbl4 (`name`);
show full create table auto_part_tbl4;
CREATE PARTITION TABLE `auto_part_tbl4` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`bid` int(11) DEFAULT NULL,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
GLOBAL INDEX /* i_name_$543e */ `i_name` (`name`) PARTITION BY KEY (`name`, `id`) PARTITIONS 24,
LOCAL KEY `_local_i_name` (`name`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`id`)
PARTITIONS 24
/* tablegroup = `tg6` */
- 当分区键不包含主键时(手动分区表),创建普通索引则是本地索引
CREATE TABLE t_order11 (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext DEFAULT NULL,
`order_detail` longtext DEFAULT NULL,
PRIMARY KEY (`id`),
index i_seller_id(`seller_id`)
) partition by hash(`buyer_id`);
show full create table t_order11;
CREATE TABLE `t_order11` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext,
`order_detail` longtext,
PRIMARY KEY (`id`),
LOCAL KEY `i_seller_id` (`seller_id`),
LOCAL KEY `auto_shard_key_buyer_id` USING BTREE (`buyer_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`buyer_id`)
PARTITIONS 24
/* tablegroup = `tg9` */
- 默认覆盖列包含主键和主表的分区键
CREATE TABLE t_order13 (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext DEFAULT NULL,
`order_detail` longtext DEFAULT NULL,
PRIMARY KEY (`id`),
GLOBAL index g_i_seller_id(`seller_id`) partition by hash(`seller_id`)
) partition by hash(`buyer_id`);
show full create table t_order13;
CREATE TABLE `t_order13` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext,
`order_detail` longtext,
PRIMARY KEY (`id`),
GLOBAL INDEX /* g_i_seller_id_$93ea */ `g_i_seller_id` (`seller_id`) COVERING (`buyer_id`) PARTITION BY KEY (`seller_id`) PARTITIONS 24,
LOCAL KEY `auto_shard_key_buyer_id` USING BTREE (`buyer_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`buyer_id`)
PARTITIONS 24
/* tablegroup = `tg9` */
show global index from t_order13;
1 |
|
- 后创建普通索引(手动分区表),也是本地索引
CREATE TABLE t_order14 (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext DEFAULT NULL,
`order_detail` longtext DEFAULT NULL,
PRIMARY KEY (`id`)
) partition by hash(`buyer_id`);
create index i_seller_id on t_order14(`seller_id`);
show full create table t_order14;
CREATE TABLE `t_order14` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext,
`order_detail` longtext,
PRIMARY KEY (`id`),
LOCAL KEY `auto_shard_key_buyer_id` USING BTREE (`buyer_id`),
LOCAL KEY `i_seller_id` (`seller_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`buyer_id`)
PARTITIONS 24
/* tablegroup = `tg9` */
分区列
默认会创建本地索引
CREATE TABLE t_order8 (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext DEFAULT NULL,
`order_detail` longtext DEFAULT NULL,
PRIMARY KEY (`id`)
) partition by hash(`buyer_id`);
show full create table t_order8;
CREATE TABLE `t_order8` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext,
`order_detail` longtext,
PRIMARY KEY (`id`),
LOCAL KEY `auto_shard_key_buyer_id` USING BTREE (`buyer_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`buyer_id`)
PARTITIONS 24
/* tablegroup = `tg9` */
- 全局索引默认以
索引列
与主键
列作为分区键并进行自动分区
create GLOBAL index g_i_bid on auto_part_tbl3(`bid`);
show full create table auto_part_tbl3;
CREATE PARTITION TABLE `auto_part_tbl3` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`bid` int(11) DEFAULT NULL,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
GLOBAL INDEX /* g_i_bid_$fa03 */ `g_i_bid` (`bid`) PARTITION BY KEY (`bid`, `id`) PARTITIONS 24,
GLOBAL INDEX /* idx_name_$d0e9 */ `idx_name` (`name`) PARTITION BY KEY (`name`, `id`) PARTITIONS 24,
LOCAL KEY `_local_idx_name` (`name`),
LOCAL KEY `_local_g_i_bid` (`bid`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`id`)
PARTITIONS 24
/* tablegroup = `tg6` */
聚簇索引
PolarDB-X新增支持聚簇索引功能,用于自动维护全局二级索引(GSI)中的覆盖列,保证聚簇索引表和主表的实时同步,所有查询均不用回表,避免因回表带来的额外开销。本文介绍如何创建并使用聚簇索引。
- 聚簇索引是一种特殊的
全局二级索引
,相关行为和限制请参考全局二级索引。 - 聚簇索引的覆盖列默认包含主表的所有列,并在主表的列发生变更时,自动同步修改聚簇索引表,保证聚簇索引表和主表的实时同步。
- 聚簇索引表也会和主表的本地索引保持同步。
调优
执行计划
EXPLAIN select * from dic_sceneorder where ProductSysNo = 103315;
算子
含义 | 物理算子 |
---|---|
下发给DN的算子 | LogicalView,LogicalModifyView,PhyTableOperation, IndexScan |
连接(Join) | BKAJoin,NLJoin,HashJoin,SortMergeJoin,HashSemiJoin,SortMergeSemiJoin,MaterializedSemiJoin |
排序 | MemSort,TopN, MergeSort |
聚合(Group By) | HashAgg,SortAgg |
数据重分布或者聚合 | Exchange Gather |
过滤 | Filter |
投影 | Project |
求并集 | Union |
设置结果集输出行数(Limit/Offset…Fetch) | Limit |
窗口函数 | OverWindow |
当涉及到多分区操作时,单纯DN无法做到,CN层面的处理必不可少,比如跨分区排序,跨分区group,跨分区过滤(having)
查询改写
通过explain optimizer + sql可以看到查询改写的具体过程。
1 |
|
职能索引推荐
EXPLAIN advisor select * from dic_sceneorder where ProductSysNo = 103315;
代价分析
1 |
|
查询执行器
执行模式
1 |
|
获取物理SQL在DN上的执行情况,比如是否命中了DN的局部索引
1 |
|