深入解析 StarRocks 物化视图:全方位的查询改写机制

小编导读:

本文将重点介绍如何利用物化视图进行查询改写。文章将全面介绍物化视图的基本原理、关键特性、应用案例、使用场景、代码细节以及主流大数据产品的物化视图改写能力对比。

物化视图在 StarRocks 中扮演着至关重要的角色,它是进行数据建模和加速查询的神器。特别是在 BI 场景中,通过预先计算 Join 和 Aggregation 操作,物化视图不仅能大幅度提升查询性能,还能显著降低存储成本。

使用物化视图通常包含以下三个阶段:

  1. 设计与创建:首先,我们需要仔细分析查询的特点,以选择构建最适合的物化视图。

  2. 视图维护:当基础表的数据发生变化时,物化视图也需要及时更新,以确保数据的一致性。

  3. 查询改写:利用预计算的数据,物化视图能有效地加速查询处理过程,提供更快的响应速度。

本文重点讨论物化视图的第三阶段:如何利用物化视图进行查询改写。StarRocks 的异步物化视图采用了广泛认可的 SPJG(Select-Projection-Join-Groupby)算法。这允许系统在用户无需修改任何查询的前提下,自动将原始查询转换为对物化视图的查询。借助物化视图中预计算的结果,这种自动化的查询改写大幅降低了计算代价,从而实现了显著的查询加速。

在典型的 OLAP 标准测试集中, 通过创建物化视图可以显著提升查询性能:

  • SSB 100GB:与传统的星形模型相比,物化视图能将总体查询耗时减少至原来的 1/3。

  • TPC-H 100GB:这种技术能加速一半的查询,平均耗时降至原来的 1/5。

基本原理

(StarRocks 物化视图改写流程)

物化视图改写的关键流程如上图所示,整体上可以划分为以下三个阶段:

  1. 预处理:在 Analyzer 处理后得到的逻辑计划树的基础上,系统会识别出相关的物化视图候选集。此阶段还包括过滤掉无法用于改写的物化视图,以缩小搜索空间并确保物化视图数据的新鲜度。

  2. SPJG 物化视图改写:应用基于cost-based的 SPJG 物化视图改写规则,自动遍历搜索空间中可用于改写的子树,并尝试进行改写,并且最终会根据 Cost Model 选择最优的改写方案。

  3. 后处理:对物化视图改写后的 Plan 执行列裁剪、谓词下推、分区裁剪等优化操作,以提升改写后 Plan 的执行性能。

举例说明,对于一条具体的查询,物化视图的改写可以分为以下几个步骤处理:

  1. 预处理:

  • 分析访问表:首先分析查询涉及的基表, 根据这些基表与物化视图之间的依赖关系,识别可能有用的物化视图

  • 候选视图筛选:对于复杂的查询可能存在大量的候选物化视图,直接考虑所有视图会导致计算开销过大。因此,因此,需要根据视图的“适用性”对候选视图进行排序,并选择一个子集进行进一步分析

  • 新鲜度验证:检查候选物化视图的数据新鲜度,若物化视图数据不满足查询的要求,则抛弃这些视图

  1. TEXT 改写

  • 当查询与某个物化视图在 AST tree/语法树结构上完全一致时,可以通过文本匹配直接将查询改写为对该视图的访问

  1. SPJG 查询改写

  • SPJG 改写适用于查询与物化视图有所差异的场景,可以对物化视图进行补偿改写,提供了更大的灵活性,但实现上也更为复杂

  • 在 SQL 优化器中应用多种规则来匹配视图和查询,对所有可能的 Query Plan 进行改写,这一过程的计算开销相对较高

  • 改写后,对于产生的所有可能的改写结果,使用 Cost Model 来评估并选择最优的改写方案

  1. 后置处理

  • 对改写后的查询计划应用更多优化器规则,如列裁剪、谓词下推和分区裁剪等

select sum(lo_revenue) as lo_revenue, d_year, p_brand
from lineorder
join dates on lo_orderdate = d_datekey
join part on lo_partkey = p_partkey
join supplier on lo_suppkey = s_suppkey
where p_category = 'MFGR#12' and s_region = 'AMERICA'
group by d_year, p_brand
order by d_year, p_brand;

关键特性

除核心能力之外,StarRocks 物化视图自动改写还包括以下关键特性:

  1. 数据一致性:

  • 内部表一致性:确保物化视图改写的结果与查询原始表结果完全一致,实现强数据一致性。

  • 过期数据处理:支持配置数据过期容忍时间,适应数据频繁变更的场景,通过 staleness 改写技术应对数据变化。

  1. 复杂查询支持

  • 多表 Join 支持:支持各种类型的 join,包括 view delta join 和 join derivability rewrite 等复杂 join 场景的改写,优化大宽表查询。

  • 聚合查询加速:通过聚合改写技术加速聚合查询,提升报表查询性能。

  • 嵌套视图改写:支持嵌套物化视图改写,解决复杂查询的改写问题,扩展改写范围。

  • 复杂表达式支持:够处理包括函数调用和四则运算在内的复杂表达式,满足复杂的分析计算需求

  1. 实时数据融合

  • 新鲜数据查询加速:利用 union 改写和 TTL 功能联合使用,加速新鲜数据查询,并实现历史数据自动回查原表。

  1. 多数据源支持

  • 逻辑视图物化:允许在逻辑视图上创建物化视图,支持基于 view 建模的场景下的查询加速

  • 外部表物化视图:支持包括 Hive、Iceberg、Hudi、DeltaLake、Paimon、JDBC(MySQL Dialet)等,提升数据湖场景下的查询性能

应用案例

在携程的 BI 平台中,通过 StarRocks MV 实现了几方面的性能加速:

  • Projection MV:在 Hive Table 基础上创建 Projection MV,发挥 StarRocks 内表和存储引擎的性能,使得关键报表能够获得几倍的性能加速。由于 StarRocks MV 能够支持 Hive Table 的自动刷新,一次创建后几乎不需要后续的维护,从而大幅降低 ETL 的维护成本

  • 嵌套视图:在 MV 的基础上,对复杂查询创建嵌套视图,以进一步加速关键报表查询。这些查询通常涉及 BI 场景中的典型操作,如 Join、Aggregation、多层聚合等复杂查询。

  • AutoMV:利用 AutoMV 能力,分析慢查询自动推荐出合适的物化视图,从而进一步减少了人工维护成本。

使用场景

Join Rewrite

StarRocks 支持 join 查询改写,支持的 join 类型包括:Inner join/cross join/left outer join/full outer join/right outer join/semi join/anti join。

下面是一个 join mv 改写的例子,建表如下:

CREATE TABLE `customer` (`c_custkey` int(11) NOT NULL COMMENT "",`c_name` varchar(26) NOT NULL COMMENT "",`c_address` varchar(41) NOT NULL COMMENT "",`c_city` varchar(11) NOT NULL COMMENT "",`c_nation` varchar(16) NOT NULL COMMENT "",`c_region` varchar(13) NOT NULL COMMENT "",`c_phone` varchar(16) NOT NULL COMMENT "",`c_mktsegment` varchar(11) NOT NULL COMMENT ""
) ENGINE=OLAP
DUPLICATE KEY(`c_custkey`)
COMMENT "OLAP"
DISTRIBUTED BY HASH(`c_custkey`) BUCKETS 12
PROPERTIES (
"replication_num" = "1"
);CREATE TABLE `lineorder` (`lo_orderkey` int(11) NOT NULL COMMENT "",`lo_linenumber` int(11) NOT NULL COMMENT "",`lo_custkey` int(11) NOT NULL COMMENT "",`lo_partkey` int(11) NOT NULL COMMENT "",`lo_suppkey` int(11) NOT NULL COMMENT "",`lo_orderdate` int(11) NOT NULL COMMENT "",`lo_orderpriority` varchar(16) NOT NULL COMMENT "",`lo_shippriority` int(11) NOT NULL COMMENT "",`lo_quantity` int(11) NOT NULL COMMENT "",`lo_extendedprice` int(11) NOT NULL COMMENT "",`lo_ordtotalprice` int(11) NOT NULL COMMENT "",`lo_discount` int(11) NOT NULL COMMENT "",`lo_revenue` int(11) NOT NULL COMMENT "",`lo_supplycost` int(11) NOT NULL COMMENT "",`lo_tax` int(11) NOT NULL COMMENT "",`lo_commitdate` int(11) NOT NULL COMMENT "",`lo_shipmode` varchar(11) NOT NULL COMMENT ""
) ENGINE=OLAP
DUPLICATE KEY(`lo_orderkey`)
COMMENT "OLAP"
DISTRIBUTED BY HASH(`lo_orderkey`) BUCKETS 48
PROPERTIES (
"replication_num" = "1"
);

基于上述的表,构建物化视图

-- MV
create materialized view join_mv1
distributed by hash(`lo_orderkey`)
as
select lo_orderkey, lo_linenumber, lo_revenue, lo_partkey, c_name, c_address
from lineorder inner join customer
on lo_custkey = c_custkey;

则如下的查询可以被改写为查询join_mv1:

-- Query
select lo_orderkey, lo_linenumber, lo_revenue, c_name, c_address
from lineorder inner join customer
on lo_custkey = c_custkey;

在 join 中,select 中支持复杂表达式改写,比如四则运算,string 函数,日期函数处理,case when 表达式,or 谓词等等。

select lo_orderkey, lo_linenumber, (2 * lo_revenue + 1) * lo_linenumber, upper(c_name), substr(c_address, 3)
from lineorder inner join customer
on lo_custkey = c_custkey;

上述的 join 改写场景是 Query 的 join 类型和表集合同 MV 相同的场景,StarRocks 中还扩展支持了以下几种 join 场景的改写。

1.1 Query delta join rewrite

query delta join 就是指查询的 join 表是物化视图中 join 表的超集场景。比如如下 query 是 lineorder/customer/part三表 join,join_mv1 只有 lineorder/customer 两表 join,StarRocks 支持将 query 改写到 join_mv1。

select lo_orderkey, lo_linenumber, lo_revenue, c_name, c_address, p_name
fromlineorder inner join customer on lo_custkey = c_custkeyinner join part on lo_partkey = p_partkey 

改写之后的 plan 如下:

1.2 View delta join rewrite

View delta join 指的是在查询中,涉及的 join 表是物化视图中 join 表的子集。这种场景的改写能力通常适用于大宽表查询。例如,在 SSB 场景中,可以构建一个包含所有表的物化视图,将多个表 join 成一个大宽表。这样,所有 SSB 查询都可以通过物化视图的透明改写来提升查询性能。测试结果表明,通过物化视图改写后的多表 join 查询,其性能可达到直接查询大宽表的水平。

为了实现 view delta join 的改写,要求物化视图中的 join 必须与查询中的 join 具有1:1的 cardinality preservation(基数保持)关系。以下是 SSB 改写的示例。在满足下列的 join 条件时,都可以进行 cardinality preservation join 改写。任何满足其中一种条件的 join,都能够进行 view delta join 的改写。

在 StarRocks 中, 可以用以下语法指定主外键关系:

CREATE TABLE `customer` (...) 
PROPERTIES ("unique_constraints" = "c_custkey" #指定唯一键
);CREATE TABLE `lineorder` (...) 
PROPERTIES ("foreign_key_constraints" = "(lo_custkey) REFERENCES customer(c_custkey);(lo_partkey) REFERENCES part(p_partkey);(lo_suppkey) REFERENCES supplier(s_suppkey)" #指定外键约束
);

对于 SSB 中的 Query,往往不会查询 MV 的所有表,但是通过指定了主外键关系,仍然能够利用物化视图改写加速,以其中一个查询为例:

--MV
CREATE MATERIALIZED VIEW lineorder_flat_mv
DISTRIBUTED BY HASH(LO_ORDERDATE, LO_ORDERKEY) BUCKETS 48
partition by LO_ORDERDATE
REFRESH manual
PROPERTIES ("replication_num" = "1"
)
AS SELECT*FROM lineorder AS lINNER JOIN customer AS c ON c.C_CUSTKEY = l.LO_CUSTKEYINNER JOIN supplier AS s ON s.S_SUPPKEY = l.LO_SUPPKEYINNER JOIN part AS p ON p.P_PARTKEY = l.LO_PARTKEYINNER JOIN dates AS d ON l.LO_ORDERDATE = d.D_DATEKEY;    
-- Query
select sum(lo_revenue) as lo_revenue, d_year, p_brand
from lineorder
join dates on lo_orderdate = d_datekey
join part on lo_partkey = p_partkey
join supplier on lo_suppkey = s_suppkey
where p_category = 'MFGR#12' and s_region = 'AMERICA'
group by d_year, p_brand
order by d_year, p_brand;

1.3 Join derivability rewrite

Join 派生改写是在物化视图(MV)的 JOIN 类型与查询(query)不一致,但 MV 的结果包含查询的结果时,进行的改写,例如 MV 使用了 OUTER JOIN,而查询是 INNER JOIN。目前分为以下两种情况:

  1. 两表 join 的情况:此时会枚举所有 JOIN 顺序和多种 JOIN 方式,检查 INNER/SEMI/ANTI/OUTER 之间是否兼容,在兼容的情况下仍然能够进行改写

  2. 三表或三表以上的 join:多表时无法枚举所有可能性,因此只做相对严格的兼容性检查

举个例子,MV 使用了 OUTER JOIN,而 Query 是 INNER JOIN, 直接改写会导致结果中包含 NULL,此时 StarRocks 会补偿一个谓词 IS NOT NULL 去保证结果的正确性。

-- MV
create materialized view join_mv3 
distributed by hash(`lo_orderkey`)
as
select lo_orderkey, lo_linenumber, c_name, sum(lo_revenue) as total_revenue, max(lo_discount) as max_discount 
from lineorder 
left join customer
on lo_custkey = c_custkey
group by lo_orderkey, lo_linenumber, c_name;-- Query
select lo_orderkey, lo_linenumber, c_name, sum(lo_revenue) as total_revenue, max(lo_discount) as max_discount 
from lineorder 
join customer
on lo_custkey = c_custkey
group by lo_orderkey, lo_linenumber, c_name;

Aggregation Rewrite

支持多表聚合查询的改写,并且支持所有的聚合函数,其中包括 bitmap_union/hll_union/percentile_union 等。

-- MV
create materialized view agg_mv1
distributed by hash(`lo_orderkey`)
as
select lo_orderkey, lo_linenumber, c_name, sum(lo_revenue) as total_revenue, max(lo_discount) as max_discount 
from lineorder inner join customer
on lo_custkey = c_custkey
group by lo_orderkey, lo_linenumber, c_name;

如下查询可被 agg_mv1 改写

-- Query
select lo_orderkey, lo_linenumber, c_name, sum(lo_revenue) as total_revenue, max(lo_discount) as max_discount 
from lineorder inner join customer
on lo_custkey = c_custkey
group by lo_orderkey, lo_linenumber, c_name;

除此最基础的场景之外, 还有一些扩展的场景。

2.1 Rollup

同时,支持聚合物化视图的上卷改写,例如当查询中的 GROUP BY 比 MV 的 GROUP BY 更少时,能够一定程度上服用 MV 的结果,但是仍然需要做二次聚合,才能得到最终结果:

2.2 Count distinct

Count distinct 计算一般应用于精确去重的场景。与普通的聚合不同在于,它通常无法利用上卷进行改写。

但是 StarRocks 支持通过 bitmap 来实现 count distinct 改写,进而实现基于物化视图的高性能精确去重:

  • 创建物化视图时,使用 bitmap_union(to_bitmap(lo_custkey))

  • 查询时,仍然使用普通的 count(distinct lo_custkey) 即可

-- MV
create materialized view distinct_mv
distributed by hash(`lo_orderkey`)
as
select lo_orderkey, bitmap_union(to_bitmap(lo_custkey)) as distinct_customer
from lineorder
group by lo_orderkey;-- Query
select lo_orderkey, count(distinct lo_custkey) from lineorder group by lo_orderkey;

Nested mv rewrite

StarRocks 支持嵌套物化视图改写。比如有如下三个物化视图,agg_mv2 是基于物化视图 join_mv2 之上构建的物化视图;agg_mv3 是基于 agg_mv2 之上构建的物化视图。通过这种方式,能够有效处理复杂的多层子查询。

Union rewrite

Union Rewrite 指的是物化视图的数据是查询的子集,仍然能够进行改写:

  • Partial Predicate:MV 谓词范围是查询的子集,此时会将差集回原表查询,再 UNION 起来

  • Partial Partition:MV 只物化了部分 Partition,此时其余的 Partition 回原表查询

4.1 Partial predicate

例如 MV 中有谓词 where lo_orderkey < 300000000

-- MV
create materialized view agg_mv4
distributed by hash(`lo_orderkey`)
as
select lo_orderkey, sum(lo_revenue) as total_revenue, max(lo_discount) as max_discount 
from lineorder
where lo_orderkey < 300000000
group by lo_orderkey;

则如下的查询会被改写:其中,agg_mv5 包含 lo_orderkey < 300000000 的数据,lo_orderkey >= 300000000 的数据通过直接读取lineorder表进行计算,最终通过union之后再聚合,获取最终结果。

-- Query
select lo_orderkey, sum(lo_revenue) as total_revenue, max(lo_discount) as max_discount 
from lineorder
group by lo_orderkey;

4.2 Partial partition

针对分区表来说,如果基于分区表构建分区物化视图,查询的分区范围是物化视图的最新分区范围的超集,查询会被 union 改写。

比如,有如下的物化视图, base 表 lineorder 的目前包含 p1-p7 分区,物化视图目前也包括 p1-p7 分区。

-- MV
create materialized view agg_mv5
distributed by hash(`lo_orderkey`)
partition by range(`lo_orderdate`)
refresh manual
as
select lo_orderdate, lo_orderkey, sum(lo_revenue) as total_revenue, max(lo_discount) as max_discount 
from lineorder
group by lo_orderkey;

如果 lineorder 新增一个 p8 分区,分区范围是[("19990101"), ("20000101")),则下面的查询会被改写为 union:

-- Query
select lo_orderdate, lo_orderkey, sum(lo_revenue) as total_revenue, max(lo_discount) as max_discount 
from lineorder
group by lo_orderkey;

其中,agg_mv5 包含 p1-p7 分区的数据,p8 分区的数据通过直接读取 lineorder 表进行计算,最终通过 union 之后再聚合,获取最终结果。

MV on views

支持从 view 上创建 MV,并且查询 view 的时候能够实现透明改写。在查询改写时会有两种方式:

  • VIEW 展开:内联整个 VIEW,当做普通的 QUERY 改写

  • VIEW 独立:将 VIEW 作为独立的算子,不考虑内容,再进行改写

比如有如下的 view

-- View
create view customer_view1 as
select c_custkey, c_name, c_address
from customer;-- View
create view lineorder_view1 as
select lo_orderkey, lo_linenumber, lo_custkey, lo_revenue
from lineorder;

则可以构建如下的物化视图,在改写的时候,MV 上的 view 会被自动展开到 view 引用的 base 表上,然后进行透明匹配改写。

-- MV
create materialized view join_mv1
distributed by hash(`lo_orderkey`)
as
select lo_orderkey, lo_linenumber, lo_revenue, c_name
from lineorder_view1 inner join customer_view1
on lo_custkey = c_custkey;

MV on External catalog

StarRocks 支持在 Hive/Hudi/Iceberg/Paimon/DeltaLake/JDBC 外表上构建物化视图,并且能够进行透明改写。上述所有的改写能力大部分在外表物化视图中都支持,具体支持程度可参考使用文档。

StarRocks 在物化视图改写上,目前还有如下限制:

  1. 不支持非确定性函数的改写,包括RAND/RANDOM/UUID/SLEEP等

  2. 在SPJG改写模式下,不支持窗口分析函数的改写;基于文本的改写,不受这个限制

  3. 在SPJG改写模式下,如果mv定义语句中包含limit/order by/union/except/intersect/minus/grouping sets/with cube/with rollup,则无法用于改写;基于文本的改写,不受这个限制

  4. 部分外表(Hudi/DeltaLake)上还不支持查询结果的强一致

能力对比

以下列出主流大数据产品在物化视图上的改写能力:

图片

总结

本文主要介绍了 StarRocks 中物化视图查询改写的技术原理,从优化器的执行流程,到对不同查询的处理 Join、Aggregation、View、Union 等,以及内部视角的反省和外部视角的对比。希望本文能够对关心技术原理的读者有所帮助,对 StarRocks 的用户带来更多的技术洞察和业务启发

参考文献:

  1. Optimizing Queries Using Materialized Views: A Practical, Scalable Solution

  2. Materialized view in Apache calcite: https://calcite.apache.org/docs/materialized_views.html

  3. Oracle:https://docs.oracle.com/en/database/oracle/oracle-database/12.2/dwhsg/advanced-query-rewrite-materialized-views.html#GUID-0906CA6B-7EE3-42E1-A598-C6541BCD9B36

延伸阅读:

StarRocks 物化视图:指标平台性能提升的新引擎

重新定义物化视图,你必须拥有的极速湖仓神器!

QPS 提升 10 倍!滴滴借助 StarRocks 物化视图实现低成本精确去重

StarRocks 技术内幕 | 多表物化视图的设计与实现

更多交流,联系我们:StarRocks

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/63522.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2. petalinux-build失败

NOTE 解决因为网络原因产生的编译错误分享详细的解决步骤 报错的情况 因为网络原因产生编译错误 现象 找不到适合的包文件(No suitable stageing package found) 不能发现文件(Fetcher failure for URL) 解决方法 采用本地加载本地文件的方式&#xff0c;步骤如下 进入…

web实验二

web实验二 2024.12.19 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>青岛理工大学</title>&l…

WebSocket入门与结合redis

WebSocket是什么 WebSocket 是一种用于在客户端和服务器之间建立双向通信的协议&#xff0c;它能实现实时、持久的连接。与传统的 HTTP 请求响应模式不同&#xff0c;WebSocket 在建立连接后允许客户端和服务器之间相互发送消息&#xff0c;直到连接关闭。由于 WebSocket 具有…

Hive是什么,Hive介绍

官方网站&#xff1a;Apache Hive Hive是一个基于Hadoop的数据仓库工具&#xff0c;主要用于处理和查询存储在HDSF上的大规模数据‌。Hive通过将结构化的数据文件映射为数据库表&#xff0c;并提供类SQL的查询功能&#xff0c;使得用户可以使用SQL语句来执行复杂的​MapReduce任…

OpenHarmony和OpenVela的技术创新以及两者对比

两款有名的国内开源操作系统&#xff0c;OpenHarmony&#xff0c;OpenVela都非常的优秀。本文对二者的创新进行一个简要的介绍和对比。 一、OpenHarmony OpenHarmony具有诸多有特点的技术突破和重要贡献&#xff0c;以下是一些主要方面&#xff1a; 架构设计创新 分层架构…

Electron-Vue 开发下 dev/prod/webpack server各种路径设置汇总

背景 在实际开发中&#xff0c;我发现团队对于这几个路径的设置上是纯靠猜的&#xff0c;通过一点点地尝试来找到可行的路径&#xff0c;这是不应该的&#xff0c;我们应该很清晰地了解这几个概念&#xff0c;以下通过截图和代码进行细节讲解。 npm run dev 下的路径如何处理&…

基础入门-Web应用蜜罐系统堡垒机运维API内外接口第三方拓展架构部署影响

知识点&#xff1a; 1、基础入门-Web应用-蜜罐系统 2、基础入门-Web应用-堡垒机运维 3、基础入门-Web应用-内外API接口 4、基础入门-Web应用-第三方拓展架构 一、演示案例-Web-拓展应用-蜜罐-钓鱼诱使 蜜罐&#xff1a;https://hfish.net/ 测试系统&#xff1a;Ubuntu 20.04 …

springboot中Controller内文件上传到本地以及阿里云

上传文件的基本操作 <form action"/upload" method"post" enctype"multipart/form-data"> <h1>登录</h1> 姓名&#xff1a;<input type"text" name"username" required><br> 年龄&#xf…

智慧城市工程:相关学点、优势、未来发展

目录 相关学点&#xff1a; 智慧城市的优势 挑战与未来发展 智慧城市工程是利用现代信息技术和数据分析手段&#xff0c;提升城市管理和服务水平&#xff0c;实现城市运行的智能化、便捷化和高效化的一种新型城市发展模式。智慧城市通过整合物联网&#xff08;IoT&#xff0…

看板工具助力餐饮与酒店行业实现数字化转型,提升管理与运营效率

在餐饮与酒店行业&#xff0c;服务质量和客户体验是衡量企业成功的关键因素。随着客户需求的不断多样化以及市场竞争的加剧&#xff0c;传统的管理模式逐渐难以满足高效运营的需求。尤其在高峰期&#xff0c;如何优化内部流程、提高服务效率和响应速度&#xff0c;成为了许多餐…

2024年CCF 非专业级软件能力认证CSP-J/S 第二轮( 提高组) 染色(color)

完整题目内容可前往下方链接&#xff1a; 染色&#xff08;color&#xff09;_C_嗨信奥-玩嗨信息奥林匹克竞赛-少儿编程题库学习中心https://www.hixinao.com/tiku/cpp/show-4118.html 若需更多真题&#xff0c;可前往题库中心查找&#xff0c;题库中心涵盖白名单赛事真题&am…

OpenIPC开源FPV之Adaptive-Link天空端代码解析

OpenIPC开源FPV之Adaptive-Link天空端代码解析 1. 源由2. 框架代码2.1 消息机制2.2 超时机制 3. 报文处理3.1 special报文3.2 普通报文 4. 工作流程4.1 Profile 竞选4.2 Profile 研判4.2.1 回退策略4.2.2 保持策略 4.3 Profile 应用 5. 总结6. 参考资料7. 补充资料7.1 RSSI 和 …

labelme标签批量转换数据集json_to_dataset

文章目录 labelme标签批量转换数据集json_to_dataset转换原理单张图片转换多张图片批量转换bat脚本循环法 标注图片提取标注图片转单通道 labelme标签批量转换数据集json_to_dataset 转自labelme批量制作数据集教程。 转换原理 在安装了labelme的虚拟环境中有一个labelme_js…

Apache Kylin最简单的解析、了解

官网&#xff1a;Overview | Apache Kylin 一、Apache Kylin是什么&#xff1f; 由中国团队研发具有浓厚的中国韵味&#xff0c;使用神兽麒麟&#xff08;kylin&#xff09;为名 的一个OLAP多维数据分析引擎:&#xff08;据官方给出的数据&#xff09; 亚秒级响应&#xff…

01云计算HCIA学习笔记

笔者今年7月底考取了华为云计算方向的HCIE认证&#xff0c;回顾从IA到IE的学习和项目实战&#xff0c;想整合和分享自己的学习历程&#xff0c;欢迎志同道合的朋友们一起讨论&#xff01; 第一章 云计算概述 ICT&#xff1a;ICT是世界电信协会在2001年的全球会议中提出的一个综…

php生成图片

前提 开启dg2库 去掉前面的;注释&#xff0c;有的可能会带.dll后缀影响不大 extensiongd2代码 <?php $file imagecreate(100,50); //先生成图片资源$color imagecolorallocate($file,255,255,255); //白色$c imagecolorallocate($file,0,100,255);imagefill($file,0…

免费GIS工具箱:轻松将glb文件转换成3DTiles文件

在GIS地理信息系统领域&#xff0c;GLB文件作为GLTF文件的二进制版本&#xff0c;主要用于3D模型数据的存储和展示。然而&#xff0c;GLB文件的使用频率相对较低&#xff0c;这是因为GIS系统主要处理的是地理空间数据&#xff0c;如地图、地形、地貌、植被、水系等&#xff0c;…

游戏何如防抓包

游戏抓包是指在游戏中&#xff0c;通过抓包工具捕获和分析游戏客户端与服务器之间传输的封包数据的过程。抓包工具可实现拦截、篡改、重发、丢弃游戏的上下行数据包&#xff0c;市面上常见的抓包工具有WPE、Fiddler和Charles Proxy等。 抓包工具有两种实现方式&#xff0c;一类…

Java中的Consumer接口应该如何使用(通俗易懂图解)

应用场景&#xff1a; 第一次程序员A写好了个基础的遍历方法&#xff1a; public class Demo1 {public static void main(String[] args) {//假设main方法为程序员B写的,此时需要去调用A写好的一个遍历方法//1.如果此时B突然发现想将字符串以小写的形式打印出来&#xff0c;则…

【常微分方程讲义1.1】方程的种类发展与完备

方程在数学历史中不断发展&#xff0c;逐步趋于完备。从最初的简单代数方程到包含函数、算子甚至泛函的更复杂方程&#xff0c;数学家通过不断的扩展和深化&#xff0c;逐渐建立起更为丰富和多元的方程类型体系。方程的种类之所以不断演变&#xff0c;部分是因为解决实际问题的…