2024 年 12 月 5 日,由 NineData 和云数据库技术社区主办,华为云、Doris 等协办单位共同举办的 2024 第二届数据库编程大赛启动。比赛要求选手仅用一条 SQL 实现 "秒杀" 100 万张火车票。历经 2 周的赛程。大赛组委会依据评测规则,最终确定8强选手排名。2024 数据库编程大赛总结
赛后,《2024 数据库编程大赛》8 强选手的决赛答辩视频与 SQL 代码一经公开,便吸引众多数据库爱好者持续关注。大家在看过 8 强选手的总结后,纷纷迸发出新的优化思路,进而向冠军发起挑战,主办方顺势推出《数据库编程大赛 - 冠军挑战活动》。
特别设立冠军挑战奖,完成挑战的选手将授予【终极 SQL 编程大师】的荣誉称号,另外性能第一名的选手的奖品为价值 2500 元的飞天茅台一瓶。此次活动于 2025 年 1 月 5 日 22:00 圆满落幕。
在本次冠军挑战活动中,最终有五位终极 SQL 编程大师诞生!他们的解题思路独具匠心,并且性能超越本次冠军进入 1 秒以内。同时恭喜卢涛选手,获得奖品为价值 2500 元的飞天茅台一瓶。
1. 终极 SQL 编程大师:卢涛
卢涛在进阶挑战解答的基础上,针对 duckdb 进行了优化:
- 利用一个 2 行的小表作为有座和无座标志,与列车表交叉连接,统一编号起始字段和结束字段,避免 OR 条件判断,解决 duckdb 不使用HASH JOIN方法连接问题并简化判断条件。
- 预先将比较字段统一转化为 4 字节整数,消除比较时的转化开销。
- 删除不必要的车厢号码字符类型转化。
2. 终极 SQL 编程大师:程宁
程宁的优化思路如下:
- 在第二届大赛冠军郭其参赛 SQL 的最大公约数基础上减少计算量,提升代码可读性。
- 修改乘客表排序方式,虽在 doris 中未提速,但在 duckdb 中数据量越大提速效果越明显。
- 简化部分 case 写法,利用 duckdb 特性,简化表生成及座位分配写法,并使用 duckdb 的表值函数。
3. 终极 SQL 编程大师:周仟荣
周仟荣解题的总体思路是围绕减少表连接行数和非必要排序展开:
- 选用 DuckDB,将乘客和座位表按起始站 - 终点站分组聚合为数组,关联展开后批量分配座位,减少表连接行数。
- 通过多个 CTE 步骤,包括生成乘客数组、列车座位信息、座位数组合并及最终分配结果输出等,完成座位分配。
4. 终极 SQL 编程大师:柳胜勋
- 柳胜勋的思路与原算法类似,对乘客和车次编号,扩展车次表时将座位号分片改为 20 一组,提前计算车次和座位后缀分配序列,节省时间。
- 在扩展train表的过程中,可以看到20个座位一个分片时,车次号是固定的。座位号的后缀其实也是能确定的,因为一个车厢正好是20排。而对于每列车来讲,这些信息也都是一样的,所以可以把车次和座位后缀的分配提前计算序列。
5. 终极 SQL 编程大师:郑凌云
算法整体思想:
- 郑凌云将算法从 mysql 转成 doris,整体思想是将 passenger 表和 train 表按 20 人或 20 个位置一组进行 join,20 为火车座位数及无座票数量的最大公约数,算法具有通用性。
算法优化细节:
- 为最小化两张表 join 的计算量,对出发站与到达站组合及无座票分别编码,将相关信息压缩至 journey_chunk_rank 整数用于 join。在 MySQL 测试多种 join 方案,如分批 join、区间比较、多值算术运算后比较,以及扩大分组规模减少火车表大小,均不如该方案简单高效。简单区间比较在出发站和到达站组合数多时有较好性能,但组合数下降时性能急剧下滑。因此采用复杂分组方式,避免最坏情况性能下降。
本次《数据库编程大赛 - 冠军挑战活动》不仅是一场技术的较量,更是数据库爱好者们交流与学习的平台。再次感谢大家对本次《数据库编程大赛》的关注和支持,欢迎加入技术交流群,后续会不断举办更多精彩的活动,欢迎各路数据库爱好者来挑战!