暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SQL编程大师张永志:从生成车票到性能优化,数据库大赛代码算法解读!

NineData 2024-12-28
328

数据库编程大赛:只用一条 SQL 秒杀 100 万张火车票

2024 第二届数据库编程大赛于 12 月 5 日正式开启初赛!由 NineData 和云数据库技术社区主办,华为云、Doris等协办单位和媒体共同举办。比赛要求选手设计一套SQL算法,只用一条 SQL 秒杀 100 万张火车票,让乘客都都能顺利坐上火车回家过年。查看赛题详情

以下是本次决赛第7名,SQL编程大师张永志的参赛介绍:

参赛选手:张永志
个人简介:十多年Oracle经验,6年MySQL经验,擅长数据库性能调优、SQL性能优化与索引设计。
参赛数据库Oracle
性能评测:百万级数据代码性能评测 4.059 秒
综合得分:74.5

以下是张永志选手的详细算法说明,结尾附完整SQL:

1.首先生成列车的车票信息。借用自增数列t_sequence,通过与train连接,生成车厢号、座位号。另外,生成10%的无座车票。为便于对车票排序,额外生成是否有座说明列。

2.以出发站和到达站点对高铁车次分组,并按照是否有座对可售车票进行顺序编号,有座车票编号在前,无座车票编号在后。

3.乘客按照出发站和到达站点进行顺序编号。

4.车票和乘客顺序编号之后,根据出发站、到达站点、顺序编号对可售座票与乘客进行外连接,即完成车票分配。

性能优化考虑

  • 由于是全量数据连接操作,表字段个数少,且表连接操作都是在中间结果集之后进行的,创建索引没有多大意义,故无需额外创建索引。
  • 若机器性能较好,可考虑添加并行hint,使用并行查询技术。
  • 可在排序内存和hash连接内存分配上多给一些,消除在磁盘上的排序。

参赛完整SQL:

    ### Oracle实现:
    with
    t_sequence as (
    select rownum as seq_no from dual connect by level <= 1600*1.1
    ),
    tmp_seat as (
    select train_id,departure_station,arrival_station,coach_number,seat_num, is_seat_flag,
    seq_no,row_number() over(partition by departure_station, arrival_station order by is_seat_flag desc, train_id, seq_no) as seat_rn
    from (
    select t1.train_id, t1.departure_station, t1.arrival_station,
    1+floor((t2.seq_no-1)/100) as coach_number,
    concat(1+trunc((t2.seq_no - floor((t2.seq_no-1)/100) * 100 - 1) /5),TRANSLATE(mod(t2.seq_no,5),'12340','ABCEF')) as seat_num,
    t2.seq_no,
    1 as is_seat_flag
    from train t1, t_sequence t2
    where t1.seat_count >= t2.seq_no
    union all
    select t1.train_id, t1.departure_station, t1.arrival_station, NULL as coach_number, '无座' as seat_num, t2.seq_no, 0 as is_seat_flag
    from train t1, t_sequence t2
    where t2.seq_no > t1.seat_count and t2.seq_no <= t1.seat_count * 1.1
    )
    ),
    tmp_passenger as (
    select t1.passenger_id, t1.departure_station, t1.arrival_station,
    row_number() over(partition by t1.departure_station, t1.arrival_station order by t1.passenger_id) as pass_rn
    from passenger t1
    )
    select t1.passenger_id, t1.departure_station, t1.arrival_station, t2.train_id, t2.coach_number,t2.seat_num
    from tmp_passenger t1 left join tmp_seat t2
    on t1.departure_station = t2.departure_station
    and t1.arrival_station = t2.arrival_station
    and t2.seat_rn = t1.pass_rn
    order by t1.passenger_id;
    《数据库编程大赛》

    下一次再聚!

    感谢大家对本次《数据库编程大赛》的关注和支持,欢迎加入技术交流群,更多精彩活动不断,我们下次再相聚!

    文章转载自NineData,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论