PostgreSQL FOR 快递公司快件跟踪表设计思考

快递随着电商的崛起逐渐火爆, 特别是电商搞大促销的阶段, 快递更是达到爆仓的状态.

如果全国电商1天生成100亿比交易的话, 快递公司的IT是怎么完成这些无纸化操作的呢, 比如数据录入, 快件的状态跟踪, 用户通过网站查询快递等等.

我没在快递公司的IT部门干过, 也没和快递公司的DBA或者架构师交流过, 以下纯属个人扯淡.

最近买了点东西, 早上查了一下快递单, 甚至一天查好几次, 我估计大多数人和我一样, 没电脑的人也可能通过打电话去查询.

突发奇想, 快递的数据库怎么支撑用户的查询和快递公司内部业务系统的更新和查询呢?

我假象的快递数据库的特点.

1. 一堆的字典表, 比如快递公司的组织结构字典表. 这种查询多, 更新少. 

要体现层次结构的话, 可以参考pg的异构数据查询举例

http://blog.163.com/digoal@126/blog/static/163877040201132843255911/

还有一个PG的插件类型, ltree, 也可以体现组织结构.

http://www.postgresql.org/docs/9.3/static/ltree.html

2. 应该会有类似的GIS系统, 计算最优路径.

3. 快递单的属性表, 包括重量, 起点终点, 保价否, 寄件人属性, 收件人属性, 价格等.

4. 快件跟踪表应该是最大的, 可以按时间分区, 老的快件跟踪记录基本上不会被查询到了. 只用作留档.

快件跟踪表记录快递的实时状态, 并且这些状态要串起来.

例如我查询的一个快递状态如下

快 件 跟 踪

2013/12/13 7:50:38

快件状态 >>

快递单号 日期时间 快件状态
3393108415 2013-12-12 17:37:27 安徽省合肥市蜀山区包河三部公司 已收件
3393108415 2013-12-12 19:30:59 安徽省合肥市蜀山区包河三部公司 已发出
3393108415 2013-12-12 20:09:50 安徽省合肥市公司 已收入
3393108415 2013-12-12 21:47:46 安徽省合肥市公司 已打包
3393108415 2013-12-12 22:01:08 合肥转运中心公司 已收入
3393108415 2013-12-12 22:05:09 合肥转运中心公司 已发出
3393108415 2013-12-13 05:11:55 杭州转运中心公司 已收入
3393108415 2013-12-13 05:43:59 杭州转运中心公司 已发出

有些快递公司提供一次查询多个快递单号.

快递的状态表的特点, 我假象它是更新少, 查询多的一个特点.

并且更新不应该出现冲突, 即多个线程同时更新同一条记录. 

那么查询多, 更新少的话, 我的建议是在跟踪表中, 一个快递单子一条记录. 

这样做的好处是, 查询时很快, 只需要扫描2个块左右 , 1个索引块, 1个HEAP块.

但是如果一个快递单子多条记录, 即每个状态插入一条, 这样的带来的是大量的数据块的扫描, 基本上每条记录都会分布在不同的数据块上. 假设平均一个快递单的跟踪记录是15条, 数据块的扫描要多14个.

那么1条记录怎么存储呢?

快递单+复合类型数组(节点时间+节点ID+状态)+rec插入时间+rec更新时间

当然, 这里不用数组也行, 只要程序能根据存储的信息分隔每个节点状态即可, 这样做的好处是结构更加松散, 适合非结构话数据, 比方说在快递结束的地方会出现派件人, 派件人的电话等, 结构和前面不一样.

对应我这个例子是: 

3393108415, [(2013-12-12 17:37:27,安徽合肥市蜀山区包河三部公司字典表里的ID,收件状态ID), (下一个状态的复合类型...), ()], 记录插入时间, 记录的更新时间

新的状态录入时, 用array_append往数组后面追加数据即可.

我们举一个实际的例子(本例省去字典表, 只为体现单行和多行的查询性能) : 

为了使生成速度快点, 我们使用NOLOGGING表, 同时关闭 autovacuum.

digoal=# create unlogged table kuaidi_log1(id int8, crt_time timestamp, nodeid text, stat text);
CREATE TABLE
digoal=# create unlogged table kuaidi_log2(id int8, comp text);
CREATE TABLE

假设每天有500W个订单, 平均每个订单20条数据的话, 需要1亿条测试数据.

pg93@db-172-16-3-150-> vi test.sql
\setrandom id 1 5000000
insert into kuaidi_log1 values (:id, now(), '浙江省圆通快递杭州分公司', '已收件');

开启16个连接使用pgbench进行插入.

pg93@db-172-16-3-150-> pgbench -M prepared -n -r -f ./test.sql -c 16 -j 4 -t 6250000
transaction type: Custom query
scaling factor: 1
query mode: prepared
number of clients: 16
number of threads: 4
number of transactions per client: 6250000
number of transactions actually processed: 100000000/100000000
tps = 79215.655001 (including connections establishing)
tps = 79216.552965 (excluding connections establishing)
statement latencies in milliseconds:
        0.001938        \setrandom id 1 5000000
        0.194045        insert into kuaidi_log1 values (:id, now(), '浙江省圆通快递杭州分公司', '已收件');
刚好1亿记录.

插入完后创建快递单的索引.

digoal=# create index idx_kuaidi_log1_1 on kuaidi_log1 (id);

kuaidi_log1表和索引的大小

digoal=# \dt+ kuaidi_log1
                         List of relations
  Schema  |    Name     | Type  |  Owner   |  Size   | Description
----------+-------------+-------+----------+---------+-------------
 postgres | kuaidi_log1 | table | postgres | 8880 MB |
(1 row)

digoal=# \di+ idx_kuaidi_log1_1
                                   List of relations
  Schema  |       Name        | Type  |  Owner   |    Table    |  Size   | Description
----------+-------------------+-------+----------+-------------+---------+-------------
 postgres | idx_kuaidi_log1_1 | index | postgres | kuaidi_log1 | 2142 MB |
(1 row)

把这些记录合并到kuaidi_log2表, 每个快递单1条.

insert into kuaidi_log2 select id, string_agg(crt_time::text||','||nodeid||','||stat, ';' order by crt_time) from kuaidi_log1 group by id;
INSERT 0 5000000

创建kuaidi_log2表的快递单号索引.

digoal=# create index idx_kuaidi_log2_1 on kuaidi_log2 (id);

kuaidi_log2表和索引大小, 索引变小了20倍, 因为只有500万条记录.

digoal=# \dt+ kuaidi_log2
                         List of relations
  Schema  |    Name     | Type  |  Owner   |  Size   | Description
----------+-------------+-------+----------+---------+-------------
 postgres | kuaidi_log2 | table | postgres | 7172 MB |
(1 row)

digoal=# \di+ idx_kuaidi_log2_1
                                  List of relations
  Schema  |       Name        | Type  |  Owner   |    Table    |  Size  | Description
----------+-------------------+-------+----------+-------------+--------+-------------
 postgres | idx_kuaidi_log2_1 | index | postgres | kuaidi_log2 | 107 MB |
(1 row)

数据对比 : 

digoal=# select * from kuaidi_log1 where id=1;
 id |          crt_time          |          nodeid          |  stat
----+----------------------------+--------------------------+--------
  1 | 2013-12-13 08:40:21.116411 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:41:22.298613 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:42:38.141089 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:43:10.396533 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:43:14.961726 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:44:22.036227 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:46:24.767686 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:46:41.418713 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:46:48.03819  | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:47:32.8119   | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:47:48.996097 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:50:54.001399 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:52:00.678307 | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:52:14.56005  | 浙江省圆通快递杭州分公司 | 已收件
  1 | 2013-12-13 08:56:45.806082 | 浙江省圆通快递杭州分公司 | 已收件
(15 rows)

digoal=# select * from kuaidi_log2 where id=1;
 id |                                                                                                                               

                                                comp                                                                                

----+-------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
  1 | 2013-12-13 08:40:21.116411,浙江省圆通快递杭州分公司,已收件;2013-12-13 08:41:22.298613,浙江省圆通快递杭州分公司,已收件;2013-12-
13 08:42:38.141089,浙江省圆通快递杭州分公司,已收件;2013-12-13 08:43:10.396533,浙江省圆通快递杭州分公司,已收件;2013-12-13 08:43:14.96
1726,浙江省圆通快递杭州分公司,已收件;2013-12-13 08:44:22.036227,浙江省圆通快递杭州分公司,已收件;2013-12-13 08:46:24.767686,浙江省圆
快递杭州分公司,已收件;2013-12-13 08:46:41.418713,浙江省圆通快递杭州分公司,已收件;2013-12-13 08:46:48.03819,浙江省圆通快递杭州分公司,
已收件;2013-12-13 08:47:32.8119,浙江省圆通快递杭州分公司,已收件;2013-12-13 08:47:48.996097,浙江省圆通快递杭州分公司,已收件;2013-12-1
3 08:50:54.001399,浙江省圆通快递杭州分公司,已收件;2013-12-13 08:52:00.678307,浙江省圆通快递杭州分公司,已收件;2013-12-13 08:52:14.560
05,浙江省圆通快递杭州分公司,已收件;2013-12-13 08:56:45.806082,浙江省圆通快递杭州分公司,已收件
(1 row)

测试kuaidi_log1的查询性能

vi test.sql
\setrandom id 1 5000000
select * from kuaidi_log1 where id=:id order by crt_time;
pgbench -M prepared -n -r -f ./test.sql -c 16 -j 4 -T 30
pg93@db-172-16-3-150-> pgbench -M prepared -n -r -f ./test.sql -c 16 -j 4 -T 30
transaction type: Custom query
scaling factor: 1
query mode: prepared
number of clients: 16
number of threads: 4
duration: 30 s
number of transactions actually processed: 349163
tps = 11635.992258 (including connections establishing)
tps = 11641.693582 (excluding connections establishing)
statement latencies in milliseconds:
        0.003351        \setrandom id 1 5000000
        1.368531        select * from kuaidi_log1 where id=:id order by crt_time;

测试kuaidi_log2的查询性能, 流水已按时间排序, 所以不需要再次排序.

vi test.sql
\setrandom id 1 5000000
select * from kuaidi_log2 where id=:id;
pgbench -M prepared -n -r -f ./test.sql -c 16 -j 4 -T 30
pg93@db-172-16-3-150-> pgbench -M prepared -n -r -f ./test.sql -c 16 -j 4 -T 30
transaction type: Custom query
scaling factor: 1
query mode: prepared
number of clients: 16
number of threads: 4
duration: 30 s
number of transactions actually processed: 1880690
tps = 62681.334228 (including connections establishing)
tps = 62711.904831 (excluding connections establishing)
statement latencies in milliseconds:
        0.002509        \setrandom id 1 5000000
        0.251047        select * from kuaidi_log2 where id=:id;

查询性能相差5倍.

这种设计方式适合写少读多的场景, 并且写的场景不会产生锁冲突. 否则不要使用这种设计.

时间: 2024-11-02 13:41:52

PostgreSQL FOR 快递公司快件跟踪表设计思考的相关文章

数据仓库专题(4)-分布式数据仓库事实表设计思考---讨论精华

一.前言 陆续有各位兄弟参加大讨论,提出了各种问题,关于分布式环境下,维表和事实表设计,进行了比较深入的探讨,在此汇集整理,分享给大家.希望能有更多人参与尽力啊,共同探索分布式数据仓库数据模型的设计. 二.纪要 [活跃]北京-RTB-胖哥(1106110976) 10:21:36  分布式模式下事实表设计思考: 做大做强事实表,做小做弱维表: [冒泡]杭州-电子病历<ruanjizhou@qq.com> 10:23:31  能举例子说明吗? 您这句话,我似懂非懂,但是确实在临床上又有非常多的问

下雪天,部分快递公司快件滞后

本报长沙讯 1月7日,记者从相关快递公司获悉,由于近期下雪,快件收发的时效性受到一定程度影响.湖南申通.韵达.圆通等公司暂未停止收件,但从湖南寄往东北.西北地区的快件时效性将打折扣. 湖南申通市场部经理蒲晓全表示,受下雪天气影响,公司发往东北.西北地区的快件,时效性很难保证,主要涉及黑龙江.吉林.辽宁.新疆.内蒙古.宁夏等地区.他建议市民通过邮政系统寄出快件.湖南韵达快递总经理马红平也表示,受下雪冰冻影响,寄往东北西北地区的快件会滞后一两天. 湖南省邮政管理局http://www.aliyun.

数据仓库专题(3)-分布式数据仓库事实表设计思考

一.前言 最近在设计数据仓库的数据逻辑模型,考虑到海量数据存储在分布式数据仓库中的技术架构模式,需要针对传统的面相关系型数据仓库的数据存储模型进行技术改造.设计出一套真正适合分布式数据仓库的数据存储模型. 二.事实表设计基础       事实表记录发生在现实世界中的操作型事件,其所产生的可度数值.事实表的设计完全依赖于物理活动,不受可能产生的最终报表的影响.事实表中,除数字度量外,事实表总是包含外键,用于关联与之相关的维度,也可以包含退化的维度键和日期/时间戳. 三.传统模式 以FS-LDM数据

多家快递公司揽收、投递运营正常,未出现“爆仓”现象

网店"双十一"促销至今已过一周,太原市各大快递公司派件情况究竟怎样?11月19日,记者从山西申通.圆通.中通快递公司了解到,各快递公司快件揽收.投递运营正常,未出现"爆仓"现象. 当天下午,山西申通快递的客服工作人员表示,该公司为了应对"双十一"疯狂网购后快件数量猛增的情况,每个快递网点均增加了人手,并且派送人员每天加班加点派送快件."虽然现在还有部分快件等待派送,但由于未出现"爆仓"现象,所以最慢再过一周时间,客户

快递公司年关掉链子“全年无休”或名存实亡

摘要: 随着春节脚步的临近,快递业又闹起了用工荒,虽然各大快递公司明确表示全年无休,但是中新网IT频道通过多种渠道了解到,部分公司快递已经停发:另外,多家快递公司均表示,春 随着春节脚步的临近,快递业又闹起了"用工荒",虽然各大快递公司明确表示"全年无休",但是中新网IT频道通过多种渠道了解到,部分公司快递已经停发:另外,多家快递公司均表示,春节期间快件会有延迟:个别快递公司表示,春节假期时发件需加额外服务费. "年关"大部分快递公司受影响 春节

“年关”大部分快递公司受影响 电商平台自建物流优势开始凸显

摘要: 随着春节脚步的临近,快递业又闹起了用工荒,虽然各大快递公司明确表示全年无休,但是中新网IT频道通过多种渠道了解到,部分公司快递已经停发:另外,多家快递公司均表示,春 随着春节脚步的临近,快递业又闹起了"用工荒",虽然各大快递公司明确表示"全年无休",但是中新网IT频道通过多种渠道了解到,部分公司快递已经停发:另外,多家快递公司均表示,春节期间快件会有延迟:个别快递公司表示,春节假期时发件需加额外服务费. "年关"大部分快递公司受影响 春节

一快递公司接手DDS北京滞留快件

本报讯(记者许前程)上周三,本报报道了DDS北京分部一夜之间人去楼空一事.目前,滞留快件已由另一家快递公司接手,但遭拖欠的货款以及员工薪酬都只能部分发还. DDS北京分部工作人员透露,目前公司员工工资均已支付完毕,共涉及约200人.所欠的去年12月份的工资按1000元算,今年1月由于工作量少,因此只按最低保障工资800元的标准发放,记者从多名员工处证实了这一消息.很多快递员对此都不太满意,因为若是正常发放,加上送货提成的话,他们原本每月可以拿到3500元左右的薪水.朝阳区人力资源和社会保障局已介

快递员在江苏省太仓市一家快递公司的派送件现场分拣快件

当日被网民戏称为"光棍节",各大电子商务网站借此大力促销,掀起双"十一"网络购物狂欢.此后的一段时间内,各家快递公司的快递员派送快件数量将大幅增加. 阿里巴巴集团宣布,其双十一促销的支付宝总销售额191亿,同比增260%,其中天猫为132亿,淘宝为59亿.同样在举行双十一促销的京东商城和苏宁易购目前未有相关数据披露. 根据天猫方面的数据,今年参与双十一的商家数达到1万家,是去年的5倍.从参与商家和电商代运营商的反馈看,针对去年双十一普遍出现的缺货.发货延迟等问题,大

快递公司禁止露天分拣快件 拒绝验视快件将不予收寄

本报讯(记者左颖)北京市快递服务规范与安全管理办法(草案)今起征意见,市民可在3月12日前登录市法制办的网站发表意见和建议. 草案细化快递从业门槛 根据草案,从事快递服务经营业务,应当依法取得快递业务经营许可.在本市申请快递业务经营许可,还应当具备下列http://www.aliyun.com/zixun/aggregation/17484.html">服务能力:具备1个以上符合标准的快件处理场所:设置4处以上符合标准的快递营业场所,面积不少于50平方米,租赁场所经营的,租期至少为1年:配