
黄友鹏(mawangmay)
作者介绍
现就职于深圳某游戏公司,是一名 Java 开发,主要负责公司的业务调优和故障处理,熟悉 MySQL,近年来研究分布式数据库。
一家运营海外休闲游戏的公司随着其业务的发展,表的数据量大幅增加,原始的单实例 MySQL 在性能方面已经无法满足业务需求,因此需要寻求新的解决方案。本文主要介绍了选用 OceanBase 的考量因素、测试情况,分享一些实践经验,给大家提供一些参考。
01.
写热点场景下,数据入库慢,叠加读性能下滑的影响,导致运营分析的数据一直有延迟,仅能获取准实时报表。
02.
测试与部署
在小规模测试过程中,用户数据突增,数据从原来的日增百万级别,直接跳跃到日增1.2亿左右,公司内部报表业务接近瘫痪,更新替换迫在眉睫。我们迅速搭建了测试环境,测试公司基本的业务流程、兼容情况,为正式部署做准备。测试过程中主要考量以下几个因素。
1. 高性能
抽取 MySQL 中多张日志、流水表的部分数据至 OceanBase 4.0单节点中,测试各类分析 SQL 的查询性能,如分组求和、总数统计等。
对比示例:模拟单表2600w的数据量,OceanBase 中全表 count(1)毫秒级响应,而在 MySQL 中执行是分钟级。
2. 低成本
数据存储方面,原来千万级别的数据在 MySQL 中大概占用超400 GB的存储量,迁移到 OceanBase 中亿级别的数据仅需260 GB。
MySQL 5.7迁移至 OceanBase 4.0时,使用了 MySQL dump 导出 MySQL 5.7数据,再使用 OBLOADER 4.0导入 OceanBase 4.0,方便快捷。
迁移至 OceanBase 4.0以后,少部分存储过程存在不兼容的情况,在代码层面做了修改,相较于分库分表的改造、运维方案,这块的人力投入比较可控。
3. 易用性
采用 OBD 方式部署单节点实例简单快捷,另外自带的 ODC 开发者工具和以前习惯使用的 Navicat 都能方便的测试 OceanBase。
基于上述测试数据,我们决定部署 OceanBase 4.0,生产环境部署信息如下。

而在实际的测试到生产过程中,线上业务飞速发展,单表日增数据量到上亿级别,导致在生产环境实际跑业务分析 SQL 时,效率不佳。因此,我们针对几张核心表的查询也做了一定的优化措施。下面以 SQL 为例展开说明,以供参考。
比如这是一张游戏的流水表,拿到用户的流水记录以后,我们在内部会统计最近几天,不同游戏、不同渠道用户的各类消费情况,根据统计的各游戏的运营信息及时调整游戏的活动策略。
CREATE TABLE `games_play_flow` (
`event_time` int(11) DEFAULT NULL COMMENT,
`game_id` int(5) DEFAULT NULL COMMENT,
`account_id` bigint(20) DEFAULT NULL,
`uid` bigint(20) DEFAULT NULL,
`channel_id` varchar(20) DEFAULT NULL,
`play_id` varchar(100) DEFAULT NULL,
`mfr_id` int(11) DEFAULT NULL,
`money_type` tinyint(4) DEFAULT NULL,
`output` bigint(20) DEFAULT NULL,
`consume` bigint(20) DEFAULT NULL,
KEY `idx_ix_event_time_63917445` (`event_time`) BLOCK_SIZE 16384 LOCAL,
KEY `idx_ix_account_id_1050842020` (`account_id`) BLOCK_SIZE 16384 LOCAL
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0
SELECT /*+ parallel(10)*/ "2022-12-09" date,
game_id,
channel_id,
sum(output) as pay_output,
sum(consume) as pay_consume
from games_play_flow
where money_type = 2
and event_time between 1670515200 and 1670601600
group by game_id ,channel_id
复制
在测试此类业务 SQL 的过程中,出现了一些问题:
1. 在日增数据量突增的情况下,OceanBase 4.0中单表分组统计 SQL 性能表现没有在测试环境的表现好。
2. 因为业务24小时均匀写入的特点,业务没有明显的高低峰期,导致当天最新数据入库时,统计信息未更新,统计最近三天运营数据时,SQL 执行计划不走索引。
我们和 OceanBase 社区的同学一起商量了解决方案,做了三方面的工作,最终保证了业务 SQL 的性能满足运营需求。
第一,重新规划运营数据的保留周期,计划仅保留1-2个月数据,并且将多张核心的单表(几亿行数据)改造为分区表,按天分区;
第二,根据 CPU 占用增加 SQL 执行的并行度,利用分区裁剪 +event_time 索引提升查询效率;
第三,针对统计信息未及时更新的问题,定时任务触发手动收集统计信息。
03.
实践总结
从整体来看,选用 OceanBase 4.0对公司业务性能的提升还是很大的,也为公司节约了很多成本。
首先,解决了 MySQL 的性能瓶颈问题,依据生产环境实际运行情况,分区表的改造加上 OceanBase 准内存架构,解决了热点表写的问题,OceanBase 4.0单机写性能是之前 MySQL 的5-6倍。
其次,针对两条业务线( MySQL 与 OceanBase )在游戏正式服的查询性能表现,对于分组聚合查询业务,我们按天进行数据分区,MySQL对单天的数据进行统计计算需要130s,而 OceanBase 仅需18s,且 OceanBase 业务线日增数据是 MySQL 业务线的2倍左右。按这样的比例来算,同配置下,在我们的业务场景下 OceanBase 的分组查询性能是 MySQL 的12倍左右。性能得到了巨大的提升。
当然,在业务切换到 OceanBase 4.0的过程中,我们也遇到了一些问题,比如上文提到的刚开始启用生产环境发现按天分区的分区表查询性能和测试环境相差较大。后来同 OceanBase 社区的同学一起快速定位到了问题,原来是当天的分区统计信息未收集到,导致查询语句走的全表扫描,通过手动触发收集分区信息后,查询性能就立马上来了,据了解,OceanBase 4.1版本将提供在线收集统计信息功能,解决这个问题。
除此以外,我们还反馈了一些关于兼容性、功能等问题,OceanBase 社区的同学也一一做了解答,可参考如下:
cpu_count 不实时生效:
https://ask.oceanbase.com/t/topic/35602067
MySQL 迁移到 OceanBase 遇到兼容问题:
https://ask.oceanbase.com/t/topic/35601905
04.
未来畅想
总的来说,在本次业务解决方案替换过程中,我们重点关注于 AP 场景下的性能优化,期间遇到的一些问题都已解决,但还有些未来可能遇到的问题,我们也做了一些规划。
1. 未来会将 OceanBase 4.0 BP1升级至正式版本。
2. 为支持业务发展,后续可能会继续扩展实例节点数,针对大表优化,可能进一步做二级分区。
3. 在运维管理方面,试用 OCP Express,简化集群管理的操作。