AnalyticDB(原ADS)分区列的最佳实践

简介: AnalyticDB 是阿里巴巴自研的在线数据库。 本文会对分区的概念进行解释,并帮助用户选择合适的分区,并尽可能修改查询来更加合理的使用分区从而提高查询性能。

AnalyticDB(简称ADS,以下ADS均代表AnalyticDB) 是阿里巴巴自研的一款面向互联网,高并发的在线数据库。目前已经广泛应用于阿里巴巴集团内部,并在阿里公有云上进行售卖,同时也可以通过阿里专有云的形式向大客户提供高效的计算分析能力。

由于ADS产品设计的目的就是要解决PB级,千万级到万亿记录的复杂查询性能。对一些传统数据库的用户来说有些概念有很大不同,需要理解其背后含义才能充分发挥ADS的最强性能。在所有的名词中分区可能是较难理解,同时又对ADS性能影响最大的一个关键点。本文会对分区的概念进行解释,并帮助用户选择合适的分区,并尽可能修改查询来更加合理的使用分区从而提高查询性能。

ADS的分区概念

如下图所示,LocalNode是ADS处理数据的计算节点。

_001_jpeg

上图中假设这个Database有m个LocalNode,表有l个分区,这个表有n列。并且这个表设计了2级分区,一共保存了90天的二级分区,每个二级分区保存一天的数据。可以看出每个LocalNode会处理 [l/m] 或者 [l/m]+1 个一级分区,每个一级分区都会保存90个二级分区的数据。每个二级分区内都保存这个表在这一天的所有列(col1,col2......coln)。

ADS的一级分区最大的目的是将数据均匀分散,这样可以充分发挥ADS分布式计算的能力,一级分区是HASH分区。而二级分区更像传统数据库的分区,目的是将数据分散到不同的存储文件上。

ADS的分区选择

ADS的一级分区列选择

如上图所示每个Database在创建的时候都会根据用户选择自动创建多个LocalNode来并发的处理数据。举个例子,如果我们创建了一个database,这个database创建的时候选择有8个ECU,对应会有8个LocalNode在同时提供服务。如果我们现在有一张订单表(orders)有8000万条记录。表的结构如下:

create table orders(
 order_id long,
 store_id long,
 order_total float,
 order_time timestamp,
 order_comment varchar,
 ...
 )
 partition by hash key(order_id)
 partition number(256);

那如何将这8000万条记录分到这8个LocalNode去处理呢? ADS使用分区列来决定怎么将8000万条记录分配到8个LocalNode,也就是上图ddl中的partition by hash key(order_id)中选择的order_id作为分区列。ADS会对order_id 进行函数计算来决定分配到哪个分区,ADS内部同时又会对256个分区进行计算来决定是哪个LocalNode去处理哪个分区。

这里简单起见我们假设所有的算法都是用取模来完成,也就是说每个LocalNode会处理(256/8)=32个分区。

如果我们假设order_id没有重复的,也就是说count(distinct order_id)=8000万,这样每个分区的记录数大约为 80,000,000/256= 31,250条记录。 根据上图所示可知,每个LocalNode处理 31,250*32 =10,000,000条记录。这样看来似乎非常简单,但这里有个最关键的概念就是数据平均分配,而且我们假设order_id是没有重复值的,但这样的情况在现实中不一定完全满足。

如果我们的查询有90%的是按照store_id进行统计分析,那这时候用order_id作为分区列就不一定是最佳选择。如果我们打算用store_id来作为分区列,我们根据经验也知道store_id在订单系统中不可能每条记录都是唯一的,也就是说


count(distct store_id) <> count(*) 

但是我们还是计划使用store_id来作为分区列,那如何在数据导入ADS前就知道是否存在数据倾斜呢?如果原始数据在odps或者oracle等其他数据库里的话,可以使用如下sql:

select count(distinct store_id),count(*) as total_cnt from orders ;
select store_id,count(*) as top_cnt from orders group by store_id order by cnt desc limit 1;

根据上述两个SQL的查询结果,有下面几种情况:

  1. 如果上面第一个查询里store_id大于分区数目,并且第二个查询里top_cnt小于 total_cnt/分区数(80,000,000/256) 31250条记录的话,可以大概率认为这个数据是没有倾斜的,store_id可以作为分区列。
  2. 如果上面第一个查询里store_id 数目小于分区列的数目,那store_id不适合作为分区列,必须使用其它列。
  3. 如果第一个查询store_id大于分区数目,但是第二个查询store_id对应的记录数大于 31250,数据会有倾斜,这时候必须先把数据导入到ADS,并尝试执行查询,如果效率还可以接受,并且数据倾斜也在可以接受范围内的话才可以继续使用,但从长远来看尽量不建议这样选择分区列。

ADS的二级分区列选择

二级分区列的选择相对一级分区列较为简单,我们推荐尽量选择和时间有关的列来作为二级分区列,因为二级分区列有一个最大的特点是会按照数量滚动删除。和上面的例子相同,我们修改为增加二级分区列,增加ds这个列,按照每天的交易数据把数据归并到某个二级分区里。

create table orders(
 order_id long,
 store_id long,
 order_total float,
 order_time timestamp,
 order_comment varchar,
 ...
 )
 partition by hash key(store_id)
 partition number(256)
 SUBPARTITION BY LIST KEY (ds bigint)
 SUBPARTITION OPTIONS (available_partition_num = 90);

这里的二级分区列我们使用交易日期ds,按照上图所示available_partition_num = 90,也就是说我们会保存90天的历史数据,当第91天的记录进入到ADS后,ADS会自动把91天前的记录删除,这样的设计可以极大的简化DBA的日常运维工作。

常见的分区设计错误

  1. 分区数目过少,小于LocalNode的数目,如上图所示,如果分区数目过少,可能会出现有的LocalNode没有分区需要处理。假设分区数目为8个,而LocalNode的个数为16个,那必然会出现有8个LocalNode没有任何数据需要处理,这时候资源会出现浪费现象。
  2. 分区数目不是LocalNode的倍数,如上图所示,如果某个表的分区数目是100个,而LocalNode的个数是64个,那么必然会出现有36个LocalNode处理2个分区,而另外28个分区需要处理1个分区。这时候的查询有很可能会出现处理36个分区的LocalNode成为慢节点。
  3. 二级分区数目过多,例如有的表每天只有30w的数据,但是需要存储1年的数据,这时候如果每天的记录都作为二级分区会导致查询效率降低。最佳选择是每个月做一个二级分区,这样每个二级分区大概有900w数据,一共有12个二级分区。
  4. 避免数据倾斜是分区的最主要目的,在数据均匀分布的情况下尽可能将查询中最常使用的谓词列或者多表Join的时候JOIN的列作为分区列可以极大提高查询效率。

查询语句中使用分区列的最佳实践

在建表语句确定以后,我们在查询语句中如何使用分区列来加速我们的查询呢?下面是几个最佳实践

在查询的谓词中尽可能添加一级分区列

假设我们的order_id和store_id是有对应关系的,例如order_id前5位就是store_id的,如果从开发角度,我们可以直接写

select * from orders where order_id=99999111;
select * from orders where order_id=88888222;

这样的查询,但如果想提高sql的查询性能,最好使用

select * from orders where order_id=99999111 and store_id=99999;
select * from orders where order_id=88888222 and store_id=88888;

在查询语句的谓词中尽可能包含二级分区列的查询条件

如果我们要查询所有商店的某一天时间段的交易数据,我们可以直接写

select store_id,sum(order_total) from orders where order_time <'2017-11-10 18:00:00' and order_time > '2017-11-10 08:00:00' group by store_id;

这样的查询,但这样的查询会导致ADS在所有的二级分区都进行一遍检索。所以如果想提高sql的查询性能,可以使用下面这样的SQL:

select store_id,sum(order_total) from orders where ds=20171110 and order_time <'2017-11-10 18:00:00' and order_time > '2017-11-10 08:00:00' group by store_id;

这样ADS可以只在20171110这个分区去做检索,提高查询效率。

结语

为了充分发挥并行计算的特点,ADS设计了一级分区列的概念,一级分区列的首要选择是避免数据倾斜。其次要尽量选择会参与谓词运算的列。同时为了减少DBA的负担,ADS又设计了二级分区的概念,二级分区列尽量按照时间去选择,二级分区列尽量也参与到谓词运算同样可以提高查询效率。

根据上文的介绍,相信用户一定能对ADS的分区概念有更深刻的理解,只要用户能设计较好的分区列,并对SQL进行简单改造,就可以体验百亿级记录表在秒级或者毫秒级返回查询结果的震撼效果,更好的帮助分析人员对业务进行快速查询,从数据中更快更多的发掘真正的业务价值。

相关实践学习
数据库实验室挑战任务-初级任务
本场景介绍如何开通属于你的免费云数据库,在RDS-MySQL中完成对学生成绩的详情查询,执行指定类型SQL。
阿里云云原生数据仓库AnalyticDB MySQL版 使用教程
云原生数据仓库AnalyticDB MySQL版是一种支持高并发低延时查询的新一代云原生数据仓库,高度兼容MySQL协议以及SQL:92、SQL:99、SQL:2003标准,可以对海量数据进行即时的多维分析透视和业务探索,快速构建企业云上数据仓库。 了解产品 https://www.aliyun.com/product/ApsaraDB/ads
目录
相关文章
|
SQL 分布式计算 运维
开源大数据 OLAP 引擎最佳实践 | 学习笔记(二)
快速学习开源大数据 OLAP 引擎最佳实践
1410 0
开源大数据 OLAP 引擎最佳实践 | 学习笔记(二)
|
12月前
|
消息中间件 SQL 存储
一文学会 ByteHouse 搭建数仓最佳实践
一文学会 ByteHouse 搭建数仓最佳实践
|
SQL BI 索引
【SQL开发实战技巧】系列(二十八):数仓报表场景☞人员分布问题以及不同组(分区)同时聚集如何实现
【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。
【SQL开发实战技巧】系列(二十八):数仓报表场景☞人员分布问题以及不同组(分区)同时聚集如何实现
|
存储 消息中间件 SQL
Flink Table Store 0.3 构建流式数仓最佳实践
阿里巴巴高级技术专家,Apache Flink PMC 李劲松(之信),在 FFA 2022 实时湖仓的分享。
Flink Table Store 0.3 构建流式数仓最佳实践
|
存储 SQL 分布式计算
AnalyticDB for MySQL最佳实践总结
随着AnalyticDB for MySQL(下文统一简称:ADB)在阿里集团各个业务线、社会上各行各业的推广应用,我们沉淀了一些最佳实践,现在笔者整理在这里,供大家参考,希望对大家有帮助。本篇文章总结了ADB表的设计的最佳经验、数据写入的最佳经验、高效查询的最佳实践,以及一些常见的问题。 说明: 1.在读这篇文章之前,请先了解ADB的产品官方文档,以提前适当了解ADB; 2.本文写的最佳实践主要针对ADB3.0,ADB2.0在原理上也同样适用。
4701 1
AnalyticDB for MySQL最佳实践总结
|
弹性计算 运维 监控
2022云栖精选—AnalyticDB MySQL 湖仓版在B站的最佳实践
陈浩 哔哩哔哩Bilibili资深数据开发专家
2022云栖精选—AnalyticDB MySQL 湖仓版在B站的最佳实践
|
存储 关系型数据库 数据管理
【最佳实践】高性价比的数据归档解决方案(DMS + AnalyticDB PostgreSQL)
发布全新数据归档方案,依托DMS + AnalyticDB PostgreSQL Serverless版本,帮助客户用低价格实现海量数据的持久化,还可以对归档数据进行完善管理、高效寻回、查看并进行分析
【最佳实践】高性价比的数据归档解决方案(DMS + AnalyticDB PostgreSQL)
|
Cloud Native 关系型数据库 OLAP
《基于云原生数据仓库AnalyticDB PG的最佳实践》电子版地址
基于云原生数据仓库AnalyticDB PG的最佳实践.ppt
93 0
《基于云原生数据仓库AnalyticDB PG的最佳实践》电子版地址
|
Cloud Native
《新氧云原生全栈数仓最佳实践》电子版地址
新氧云原生全栈数仓最佳实践.ppt
68 0
《新氧云原生全栈数仓最佳实践》电子版地址
|
存储 关系型数据库 MySQL
MySQL数据库(13):列属性(字段属性)
MySQL数据库(13):列属性(字段属性)
117 0

热门文章

最新文章

相关产品

  • 云原生数据仓库AnalyticDB MySQL版