欢迎来到格策美文网
更新日期:2025-06-15 15:27
写作核心提示:
撰写关于网络计划优化的内容作文时,应注意以下事项:
1. 明确主题:首先,要明确作文的主题,即网络计划优化的概念、目的、方法、应用等。确保作文内容围绕主题展开,避免偏离主题。
2. 结构清晰:一篇优秀的作文应具备清晰的结构,包括引言、正文和结论。引言部分简要介绍网络计划优化的背景和意义;正文部分详细阐述网络计划优化的内容,如优化方法、步骤、应用等;结论部分总结全文,强调网络计划优化的重要性。
3. 逻辑严谨:在论述网络计划优化的过程中,要保持逻辑严谨,论证充分。注意各部分之间的衔接,确保论述连贯。
4. 举例说明:为了使文章更具说服力,可以结合实际案例进行说明。例如,介绍某企业在网络计划优化方面的成功经验,或分析某项目在网络计划优化过程中遇到的问题及解决方法。
5. 语言表达:作文的语言表达要准确、简洁、生动。避免使用过于复杂的词汇和句式,以免影响读者的理解。
6. 注意数据支持:网络计划优化涉及大量数据,如项目进度、资源分配等。在论述过程中,应引用相关数据,以增强说服力。
7. 强调创新:在介绍网络计划优化方法时,可以强调创新性,如采用新技术、新方法等。这有助于提升文章的吸引力。
8. 关注应用领域:网络计划
作者:京东零售 姜波
本文主要针对供应链计划业务发展过程中系统产生的瓶颈问题的解决方案进行阐述,并且分享一些问题解决过程中用到的一些工具方法,希望对其他业务同类问题提供启发,原理细节不着重介绍,如有兴趣欢迎一起探讨。
供应链计划业务目前数据库主要使用了Tidb和Clickhouse,Tidb用于存储计划数据、维度数据、业务配置等数据,Clickhouse用于存储量级比较大的历史参考数据。随着业务发展,业务需要在某些场景下对这些历史数据做一些过滤或配置一些业务Tag,并且这些过滤条件和业务Tag需要支持更新、删除。最初我们的解决方案中部分配置的生效方案是将这些配置存在Tidb,然后通过离线抽数到离线大数据表,然后在离线大数据平台对历史数据进行处理后推送到Clickhouse再使用,但是这样业务的生效周期就是T+1,对业务使用的体验非常不友好。还有一些配置生效方案是将Tidb的业务配置和Clickhouse中的历史数据全部读取出来,在实例的内存中进行聚合处理,这种解决方案会导致实例的内存不够用,经常OOM,影响系统稳定性。而且在内存中处理这些数据的逻辑比较重,致使某些场景下的查询非常慢,个别情况一次查询响应时长会达到10秒以上,严重影响用户使用体验。
针对以上生效周期长、聚合查询内存占用大、查询慢这些问题,我们在实验后发现,无论实在Tidb还是在Clickhouse中,通过sql聚合查询直接输出聚合结果,要比在内存中聚合要快很多,而且对db也不会造成很大的压力,其效果大概是在内存中执行5秒的逻辑,等比转化到sql中,大约300ms就可以输出结果,这中间涉及IO传输、DB的聚合优化、索引等,具体原理不做过多阐述,有兴趣自行网上查阅即可。 主要优化方向就是将业务配置数据同步到Clickhouse中一份,然后分别在Tidb和Clickhouse中join输出结果数据。
最初我们查阅官方文档后,决定使用ReplacingMergeTree,然后在使用时使用final关键字保证数据去重,官方文档:
https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/replacingmergetree,官方文档的建表和查询示例:
官方文档的示例过于简略了,相当于“Hello Word”,并不能满足我们实际使用需求,想要实际在生产环境应用,需要建成下面这样:
CREATE TABLE IF NOT EXISTS 库名.blacklist ON CLUSTER xx
(
`dept_id_1` Int32 COMMENT '一级部门ID',
`dept_id_2` Int32 COMMENT '二级部门ID',
`dept_id_3` Int32 COMMENT '三级部门ID',
`saler` String COMMENT '销售erp',
`pur_controller` String COMMENT '采控erp',
`update_time` DateTime COMMENT '更新时间',
`is_deleted` UInt8 COMMENT '有效标识 0:标识未删除 1:表示已删除'
)
ENGINE = ReplicatedReplacingMergeTree('/clickhouse/xx/jdob_ha/sop_pre_mix/blacklist/{shard_dict}', '{replica_dict}', update_time)
ORDER BY (dept_id_3, saler, pur_controller)
SETTINGS storage_policy ='jdob_ha';
关于上面的建表语句,有几个要点需要解析一下
第一,ReplacingMergeTree需要写成
ReplicatedReplacingMergeTree,这个参考了京东ck运营文档里的解释
第二,【'/clickhouse/xx/jdob_ha/库名/blacklist/{shard_dict}', '{replica_dict}',】 这个信息不用太关注,是京东存储元数据的key,符合范式即可;
第三,后面跟的update_time ORDER BY,这个有点意思,以上面那个表举例,就是在用final查询 或者 Optimize手工合并时,用ORDER BY中的dept_id_3, saler, pur_controller作为唯一业务主键,用update_time排序,保留最后一条
第四,当前建表方式属于维表模式,维表模式简单说就是每个节点存储一份全量数据。对于维表,如果使用分布式表使用join会有remote查询,节点之间的通讯会增加sql耗时。后面说为什么选择使用维表模式。
今天我们主要说一说本地Join,为什么主要说它呢,第一因为它好,第二因为这次我用了
在Clickhouse中,与本地join对应的是Global Join,就拿最简单的两表join来说,Clickhouse的执行流程是:左表,先在每个分布式节点查一次,然后将查询结果远程传输到聚合节点上,右表,也是先在每个分布式节点查一次,然后将查询结果远程传输到聚合节点上,再在聚合节点上join两份结果,最终输出;本地join是在每个分布式节点上进行join,然后将每个节点的join结果远程传输到聚合节点上,合并结果最终输出;两者对比,本地join的性能和资源开销都远超Global Join。
如果是两张分布式表,那就要保证分布函数要完全一致,举个例子,我们平时建分布式表的语句如下:
-- 分布式表
CREATE TABLE IF NOT EXISTS sop_pre_mix.history ON CLUSTER xx AS sop_pre_mix.history_local ENGINE = Distributed
(
'xx',
'sop_pre_mix',
'history_local',
rand()
) ;
分布函数就是这个rand(),如果想要对两个分布式表使用本地join,就要保证这个分布函数对于维度相同的数据,算出来完全一致的结果,rand()肯定是不能用,可以参考一致性hash算法。
我们本次使用的场景,左表是一个分布式表,是纯散列的,右表我建成了维表,维表上面我们也写了它的形式,每个节点存储一份全量数据,刚好命中可以使用本地join的场景。
另外,本地join对于sql语法上也有要求,我就踩了一下语法的这个坑
在京东Clickhouse运维文档里摘录了一下精华,本地 Join是用 a.dis join b.local,对于左表a(分布式表)的过滤条件需要写成 select * from a.dis join b.local where a.cond1(千万不能写成子查询的 如 select * from (select * from a.dis where a.cond1 )join b.local ),这样没法正确的执行本地join,使得查询结果不正确,对于b 本地表的过滤条件则需要放到子查询中,那么正确的样式应该是select * froma.dis join (select * from b.local where b.cond2) where a.cond1.
语法踩坑:低版本引擎的Clickhouse,本地join时,维表需要带库名前缀,不然执行算子会报找不到表的错误,对应下面sql片段【
sop_pre_mix.sop_sale_plan_rule_core_dim】,这里必须写上sop_pre_mix
左表的建表语句(分布式表模式),数据量约2.9亿
CREATE TABLE IF NOT EXISTS sop_prod_mix.sop_sale_history_week_local ON CLUSTER xx
(
dept_id_1 Int32 COMMENT '一级部门id',
dept_name_1 String COMMENT '一级部门名称',
……一堆维度指标字段,略
sale_amount_lunar_sp Decimal(20, 2) COMMENT '同期自营销售出库金额',
dt String COMMENT '数据日期'
)
ENGINE = ReplicatedMergeTree
(
'/clickhouse/LFRH_CK_Pub_115/jdob_ha/sop_prod_mix/sop_sale_history_week_local/{shard}',
'{replica}'
)
PARTITION BY dt
ORDER BY (dept_id_1,dept_id_2,dept_id_3,saler,pur_controller,cate_id_3,ym,ymw)
SETTINGS storage_policy = 'jdob_ha',
index_granularity = 8192;
-- 分布式表
CREATE TABLE IF NOT EXISTS sop_prod_mix.sop_sale_history_week ON CLUSTER xx AS sop_prod_mix.sop_sale_history_week_local ENGINE = Distributed
(
'xx',
'sop_prod_mix',
'sop_sale_history_week_local',
rand()
) ;
右表的建表语句(维表模式),数据量约4500+条
CREATE TABLE IF NOT EXISTS sop_pre_mix.sop_dim_blacklist ON CLUSTER xx
(
`dept_id_1` Int32 COMMENT '一级部门ID',
`dept_id_2` Int32 COMMENT '二级部门ID',
`dept_id_3` Int32 COMMENT '三级部门ID',
`saler` String COMMENT '销售erp',
`pur_controller` String COMMENT '采控erp',
`update_time` DateTime COMMENT '更新时间',
`is_deleted` UInt8 COMMENT '有效标识 0:标识未删除 1:表示已删除'
)
ENGINE = ReplicatedReplacingMergeTree('/clickhouse/xx/jdob_ha/sop_pre_mix/sop_dim_blacklist/{shard_dict}', '{replica_dict}', update_time)
ORDER BY (dept_id_3, saler, pur_controller)
SETTINGS storage_policy ='jdob_ha';
命中本地join的查询sql
此sql只是动态sql生成的其中一种,实际项目中动态场景很多,主要依赖mybatis动态sql实现
SELECT
a.ymw AS ymw,
a.dept_id_2 AS dept_id_2,
a.dept_id_3 AS dept_id_3,
a.week AS week,
a.cold_type AS cold_type,
a.year AS YEAR,
a.net_type AS net_type,
a.saler AS saler,
a.pur_controller AS pur_controller,
a.dept_id_1 AS dept_id_1,
a.month AS MONTH,
a.ym AS ym,
CASE
WHEN a.dept_id_1 != c.dept_id_1
OR c.dept_id_1 IS NULL
THEN - 100
ELSE c.core_dim_id
END AS core_dim_id,
CASE
WHEN a.dept_id_1 != c.dept_id_1
OR c.dept_id_1 IS NULL
THEN - 100
ELSE c.core_dim_id
END AS brand_id,
SUM(initial_inv_amount) AS initial_inv_amount,
……一堆指标,略
SUM(gmv_lunar_sp) AS gmvLunarSp
FROM
sop_pur_history_week a
LEFT JOIN
(
SELECT
dept_id_2,
dept_id_3,
pur_controller,
saler
FROM
sop_pre_mix.sop_dim_blacklist final
WHERE
is_deleted = 0
AND dept_id_3 IN(12345, 23456,……)
)
b
ON
a.dept_id_3 = b.dept_id_3
AND a.pur_controller = b.pur_controller
AND a.saler = b.saler
LEFT JOIN
(
SELECT
dept_id_1,
dept_id_2,
dept_id_3,
pur_controller,
saler,
core_dim_id
FROM
sop_pre_mix.sop_sale_plan_rule_core_dim final
WHERE
is_deleted = 0
AND dept_id_3 IN(12345, 23456,……)
AND core_dim_id IN(12310)
AND plan_dim = 'brand'
)
c
ON
a.dept_id_1 = c.dept_id_1
AND a.dept_id_2 = c.dept_id_2
AND a.dept_id_3 = c.dept_id_3
AND a.saler = c.saler
AND a.pur_controller = c.pur_controller
AND a.brand_id = c.core_dim_id
WHERE
dt = '2023-12-16'
AND a.dept_id_3 IN(12345, 23456,……)
AND a.brand_id IN(12310)
AND
(
a.dept_id_3 != b.dept_id_3
OR b.dept_id_3 IS NULL
)
GROUP BY
a.ymw,
a.dept_id_2,
a.dept_id_3,
a.week,
a.cold_type,
a.year,
a.net_type,
a.saler,
a.pur_controller,
a.dept_id_1,
a.month,
a.ym,
c.dept_id_1,
core_dim_id
走本地join和不走本地join对资源开销的差别
很明显能看到走本地join的查询行数和内存占用是小了很多的,我们测试用的这个集群是9分片18节点的,就节约了十倍多的资源……分片越多效果越明显
这部分见我另外一篇神灯文章,TiCDC接入JDQ实践:
http://sd.jd.com/article/41284?shareId=54243&isHideShareButton=1
首先,解决了常规查询情况下实例经常OOM的问题;
其次,对于查询性能也有了稳定的提升
下面是我在测试环境对比的一些实验数据:(线上实际性能比图中都要好)
随着人工智能技术的飞速发展,各种人工智能模型在不同行业中得到了广泛应用。本文将详细介绍四大类常见的人工智能模型——大语言模型(LLM)、经典机器学习模型、经典深度学习模型和运筹优化模型——及其在实际场景中的应用。
人工智能模型是基于数学、生物学、计算机科学等多种学科知识构建的算法系统,在给定输入下实现数据驱动或者规则驱动的建模工作,进而完成预测、分类、规划或生成等模拟人类智能的任务。
这里综合各行业中常见的智能应用案例,将人工智能模型划分为四大类:大语言模型(LLM)、经典机器学习模型、经典深度学习模型、运筹优化模型,并对各类模型的应用场景做简要说明。前三类人工智能模型可以被进一步归纳为数据驱动模型,而运筹优化模型可被归纳为规则驱动模型。这里由于篇幅原因,不再介绍专家系统等其他的规则驱动模型。
大语言模型(Large Language Model, LLM)是基于大规模数据训练得到的深度神经网络模型,可以实现面向文本模态的文本理解和生成,以及通过扩展技术架构实现对图像、音频等非文本模态的理解与推理。
目前各行业对大语言模型的应用探索层出不穷,但主要集中在生成式场景,包括:
经典机器学习模型基于统计学习理论,依赖人工特征工程与非深度神经网络模型对输入数据的概率分布进行学习。该类模型往往具备较强的数学理论基础和可解释性,同时具备模型参数量小、中小规模数据驱动等特点。
经典机器学习模型多用于表格型数据的分类、预测等应用场景。比如在金融风控场景下,对客户的信用风险进行分级或者欺诈检测;以及在电商场景下,对广告的点击率进行预测等。
经典深度学习模型是基于多层神经网络架构的端到端模型,可依赖GPU做加速训练,核心特征是自动特征提取、非结构化高维数据处理、大规模数据驱动。
针对图像/语音/文本/时序等非表格型的数据识别与处理,经典深度学习模型往往体现出较优异的效果。比如在图像识别场景中,使用深度卷积神经网络做视频安防、制造业缺陷检测、人脸识别、拍照搜题等。
同时,深度学习模型也可以集成到强化学习框架中,支持智能体更好地学习自身动作与外部环境的互动关系。在实际应用中,研究人员可以使用深度强化学习模型,去增强游戏NPC的操作水平,提升玩家的操作体验。
运筹优化模型是一种基于数学规划求解方法与启发式算法的决策模型。它依赖于规则而不依赖数据,在定义目标函数和约束条件之后,能通过确定性的算法找到最优解或者满意解,在运筹类问题的解决上能与上述模型形成应用互补。
运筹规划模型多用于以下场景:
最后,想从“输入-模型-输出”的映射框架上,对运筹优化类模型与大语言模型等数据驱动模型做下对比讨论。人工智能模型的本质是通过数据驱动或规则驱动的方式,构建具有泛化能力的、从输入到输出的映射关系。
对于大语言模型等数据驱动的模型而言,输入是训练数据,模型是通过数据驱动参数优化的参数化函数,输出是智能任务执行结果(如分类/生成等)。
而运筹优化模型仍然可以纳入到“输入-模型-输出”的映射框架。此时,输入是当前人工智能问题的约束条件和目标函数,模型是通过固定数学公式表达的确定性函数,输出是智能任务执行结果(最优决策等)。所以,运筹优化模型可以看作一种规则驱动的确定性映射。
此外,在解决复杂的人工智能问题时,运筹优化与数据驱动模型呈现出融合应用的趋势,从而利用确定性函数的精确性,更好地改善从数据中学习的泛化能力。比如在基于深度强化学习的自动驾驶车辆路径规划中,数据驱动模型和运筹优化模型各司其职:数据驱动模型可以通过丰富的车辆驾驶行为与交通环境数据,学习应对交通变化的驾驶策略;运筹优化模型可以在每一步策略的执行中选择局部最优解(如最短路径)。
本文由 @明思AI 原创发布于人人都是产品经理。未经作者许可,禁止转载
题图来自Unsplash,基于CC0协议
该文观点仅代表作者本人,人人都是产品经理平台仅提供信息存储空间服务
本站部分资源搜集整理于互联网或者网友提供,仅供学习与交流使用,如果不小心侵犯到你的权益,请及时联系我们删除该资源。