当前位置: 首页 > news >正文

【性能优化】表分桶实践最佳案例

分桶背景

随着企业的数据不断增长,数据的分布和访问模式变得越来越复杂。我们前面介绍了如何通过对表进行分区来提高查询效率,但对于某些特定的查询模式,特别是需要频繁地进行数据联接查或取样的场景,仍然可能面临性能瓶颈。此外,随着数据的不断积累,可能会出现某些分区数据量过大,导致查询和处理效率受到影响。

为了更细粒度地管理和优化数据存储与访问,数据分桶(Bucketing)技术逐渐受到了关注,即对指定列的哈希值将其分配到固定数量的子集中(桶),保障数据的均匀分布,从而为复杂查询提供了更高效的处理方式

image.png

为什么要分桶

数据分桶通过对特定列的值进行哈希处理,帮助您更好地均匀分布数据、优化特定模式的查询,其优势如下:

  • 优化特定查询模式: 对于涉及桶列的JOIN和过滤操作,分桶可以大大加速查询,因为它能确保只有相关的桶被访问和处理。例如,基于桶键的 JOIN 操作可以在 map 阶段执行,避免了 shuffle 和 reduce 阶段的开销。
  • 此外,当查询的谓词包含分桶键时,可快速定位到具体的分桶,极大减少数据扫描范围,提升查询效率
  • 增加数据访问的预测性: 由于数据是基于哈希值进行分桶的,所以系统可以准确地知道哪些数据位于哪个桶中。这为数据访问提供了更高的预测性,从而进一步提高了查询性能。

何时分桶

数据分桶是一种大数据优化策略,主要目的是提高查询性能,在决定是否对表进行分桶时,需要综合考虑以下几个因素,以确保分桶对系统性能和数据管理带来实际的好处:

  • 高频的连接操作: 当两个大表需要经常进行连接操作,并且连接基于某个特定的列,经常因为数据移动而产生大量的 Shuffle 读写,拖慢了查询效率。
  • 频繁的聚合操作: 对于需要频繁执行的聚合操作,如果按照聚合的键进行数据分桶,可以大大提高查询性能,因为每个节点可以独立地完成其桶内的聚合操作。

设计表分桶策略

选择合适的分桶键是分桶优化成功的关键。以下是一些选择合适分桶键的指南和考虑因素:

步骤说明
分析查询需求● 常用的 JOIN 列:重点关注经常执行 JOIN 操作的列,基于桶键的 JOIN 可以在 Map 阶段执行,避免了 Shuffle 阶段的开销。
● 常用的 WHERE 子句列:重点关注经被用作过滤条件的列,将其作为分桶键可避免全表或分区扫描,只需扫描特定桶,从而帮助提高查询效率,并确保数据在桶之间的均匀分布。
了解数据特征● 分析数据在列上的分布情况,一个理想的分桶键应该有较大的基数和较少的重复值,避免桶中的数据不均衡。
选择分桶列数量● 多分桶列:适用于处理高任务并行度的查询,假设数据的一个主要特征或多个特征经常被一起查询或用于 JOIN 操作,即使查询条件没有涵盖所有分桶列的等值条件,该查询也可通过扫描关联的分桶,提高任务执行的并行度。
● 单分桶列:适用于高并发的点查询,使其只需扫描与该键匹配的特定桶,减少不同查询之间的 I/O 干扰,并提高系统的响应时间。
确认分桶数● 默认情况下,分桶数由 ArgoDB 自动计算,可覆盖大部分业务场景,即 数据磁盘总数 * 5,然后取比起大的相邻质数,例如磁盘数为 12,先将其乘以 5,再取相邻质数,则默认分桶数为 61。
● 如果表执行了分区操作,推荐单个分区中,分桶的数据规模为 50~100 MB,既可以避免文件过小触发小文件合并,给文件管理带来额外开销,同时也避免了 Block 文件数过多导致查询启动的 task 数过多影响执行和并发效率,需要注意应避免将分桶数设置为 31 及其倍数,减少潜在的哈希冲突。
在具体实践中,您也可以使用小规模数据量的表来尝试使用不同的分桶键,比较分桶获得到的查询收益,找出为您提供最佳性能的选择,此外,随着业务数据特性、查询需求的变化,可能还需要定期评估分桶键合理性。

最佳实践

创建分桶表

场景介绍

XYZ 是一家全球知名的电子产品零售商,主营智能手机、耳机、笔记本电脑等电子产品。近期,该企业注意到某些产品的退货率居高不下。高退货不仅影响了公司的利润,还可能导致顾客的不满和对品牌的不信任。为了深入研究这一问题,该企业希望通过分析历史业务数据,识别产品质量问题、优化库存管理,从而能够更加聚焦地改进其产品和服务,在竞争激烈的零售市场中保持领先地位。

接下来,我们以 TPC-DS 样例数据集为例,演示在搭建退货数据分析的数据仓库过程中,如何通过数据分桶来提升数据查询性能,我们用到的表分别为:

  • store_sales*:存储了商品的销售数据,约 2.88 亿*条数据(*38.1 GB)且持续增长中。
  • sales_returns*:存储了商品的退货数据,约 2888 万*条数据(*3.2 GB)且持续增长中。
  • item*:存储了商品信息,共 20.4 万条数据,该表作为上两个事实表的共同维度表。

简化后的 ER 关系图如下:

image.png

操作流程

1. 分析查询需求

本案例中,XYZ 公司的数据分析师希望查询特定日期范围内,找出销售数据良好但退货率较高的商品,希望通过对查询结果的分析,帮助质量团队和市场团队针对性的深入分析具体品类。

即关键的查询列对象为日期*、商品名称、销量和*退货量,从而基本确定查询语句中,要执行条件过滤的列、关联查询的列和执行算术运算的列。

2. 评估数据表规模和预计的查询设计,初步确认分桶键。

本案例中,我们的事实表 store_sales 和 store_returns 的数据规模都非常大,预计需要通过 Join 查询 item 表的方法来分析销售数量和退货数量等信息,所以我们初步选择将 store_sales 表的 ss_item_sk 列作为分桶键,将 store_returns 表的 sr_item_sk 列作为分桶键,即均为单列分桶,此场景下,两个大的事实表选择相同的分桶键有助于更好地提升查询性能。

除此以外,前面提到我们在分析退货数据时还希望能够基于时间范围来查询,例如为后续的环比同比来提供数据支持,验证商品质量改进是否取得预期效果,我们还可以基于时间来执行分区来提升查询效率。

3. 了解分桶键的数据特性。

初步选择分桶键后,我们还需要关注分桶键的数据分布情况,确保具有高度的数据离散性,从而避免数据发生倾斜。例如依次执行下述语句,分别查看 store_sales 表的 ss_item_sk 列和 store_returns 表的 sr_item_sk 列值中 ,排名前 5 个和倒数 5 个的数据占比,从而辅助我们判断数据分布情况。

-- 查看 store_sales 表的 ss_item_sk 列值分布情况
WITH partition_percentages AS (
   SELECT ss_item_sk, COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() AS percentage
   FROM store_sales
   GROUP BY ss_item_sk
)
SELECT ss_item_sk, percentage, 'top' AS distribution_type
FROM partition_percentages
ORDER BY percentage DESC
LIMIT 5
UNION ALL
SELECT ss_item_sk, percentage, 'bottom' AS distribution_type
FROM partition_percentages
ORDER BY percentage ASC
LIMIT 5;

-- 查看 store_returns 表的 sr_item_sk 列值分布情况
WITH partition_percentages AS (
   SELECT sr_item_sk, COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() AS percentage
   FROM store_returns
   GROUP BY sr_item_sk
)
SELECT sr_item_sk, percentage, 'top' AS distribution_type
FROM partition_percentages
ORDER BY percentage DESC
LIMIT 5
UNION ALL
SELECT sr_item_sk, percentage, 'bottom' AS distribution_type
FROM partition_percentages
ORDER BY percentage ASC
LIMIT 5;

输出结果分别如下,可以看到数据相对均衡,满足分桶键的值具有高度离散性的要求。

image.png image.png

除上述方法外,您还可以通过数据采样、标准差、直方图等方法来辅助判断数据分布的均衡情况。

4. 默认情况下,分桶数由 ArgoDB 自动计算(可覆盖大多数业务场景),如需手动指定,可参考前面介绍的分桶数选择介绍,结合场景、数据规模与集群状态来综合考虑,来设定分桶数量。

让我们来带入本次案例来计算分桶数,由于我们还希望对日期进行过滤查询,为更快地过滤数据,我们还为 store_sales 表设计了分区,具体数据如下:

表名称原始 TXT 格式表大小入库后预估大小(平均压缩比 3:1)分区数分桶容量计算基数
store_sales38.1 GB12.7 GB20(按季度分区)38.1 ÷ 3 ÷ 20 = 0.635 GB
store_returns3.2 GB1.07 GB3.2 ÷ 3 = 1.07 GB

通过上述计算,我们得到了分桶容量的计算基数,将其值转换为 GB 单位,然后分别除以 50 (每分桶推荐数据规模),store_sales 和 store_returns 的分桶数分别为 13 和 22*(四舍五入),再取其相邻的质数,则分别是 *13 和 23**。

前面我们计算得出这两个表的初始分桶数较为接近,考虑后续可能会利用到 Bucket Join 方法进一步提升关联查询性能,此处我们将分桶数设置相同,若设置为 23 可能导致 store_sales 表存储的 Block 文件数过小,所以此处我们将两个表的分桶数均暂定为 13,表数据的分区分桶规划如下:

image.png

5. 为保障数据的均匀分布,依次执行下述命令,基于我们选择的分桶键来执行 HASH 算法,预估数据分布情况,数字 13 为分桶数。

-- 查看 store_sales 表的数据分桶预估情况
SELECT
   hash(ss_item_sk) % 13 AS bucket,
   COUNT(*) / (SELECT CAST(COUNT(*) AS FLOAT) FROM store_returns) AS proportion
FROM
   store_sales
GROUP BY
   hash(ss_item_sk) % 13;

-- 查看 store_returns 表的数据分桶预估情况
SELECT
   hash(sr_item_sk) % 13 AS bucket,
   COUNT(*) / (SELECT CAST(COUNT(*) AS FLOAT) FROM store_returns) AS proportion
FROM
   store_returns
GROUP BY
   hash(sr_item_sk) % 13;

查询结果如下,符合我们对数据均衡分布的预期:

image.png

image.png

6. 通过 Beeline 登录至 ArgoDB 数据库,执行下述命令创建分桶表。

i. 创建 store_sales 表,为其划分数据分区并指定分桶数量。

如您的查询场景经常涉及排序、聚合或范围查询,推荐在建表时将其相关字段作为桶内排序键,如设置多个排序键,建议优先级为分区键 > 分桶键 > 其他字段,具体语法介绍,见《开发者指南》。
CREATE TABLE store_sales(
        ss_sold_time_sk INTEGER ,
        ss_item_sk INTEGER NOT NULL,
       ss_customer_sk INTEGER ,
        ss_cdemo_sk INTEGER ,
        ss_hdemo_sk INTEGER ,
        ss_addr_sk INTEGER ,
        ss_store_sk INTEGER ,
        ss_promo_sk INTEGER ,
        ss_ticket_number BIGINT NOT NULL,
        ss_quantity INTEGER ,
        ss_wholesale_cost FLOAT ,
        ss_list_price FLOAT ,
        ss_sales_price FLOAT ,
        ss_ext_discount_amt FLOAT ,
        ss_ext_sales_price FLOAT ,
        ss_ext_wholesale_cost FLOAT ,
        ss_ext_list_price FLOAT ,
        ss_ext_tax FLOAT ,
        ss_coupon_amt FLOAT ,
        ss_net_paid FLOAT ,
        ss_net_paid_inc_tax FLOAT ,
        ss_net_profit FLOAT )
PARTITIONED BY RANGE(ss_sold_date_sk INTEGER) (
        PARTITION p1998q1 VALUES LESS THAN (2450905),
        PARTITION p1998q2 VALUES LESS THAN (2450996),
        PARTITION p1998q3 VALUES LESS THAN (2451088),
        PARTITION p1998q4 VALUES LESS THAN (2451180),
        PARTITION p1999q1 VALUES LESS THAN (2451270),
        PARTITION p1999q2 VALUES LESS THAN (2451361),
        PARTITION p1999q3 VALUES LESS THAN (2451453),
        PARTITION p1999q4 VALUES LESS THAN (2451545),
        PARTITION p2000q1 VALUES LESS THAN (2451636),
        PARTITION p2000q2 VALUES LESS THAN (2451727),
        PARTITION p2000q3 VALUES LESS THAN (2451819),
        PARTITION p2000q4 VALUES LESS THAN (2451911),
        PARTITION p2001q1 VALUES LESS THAN (2452001),
       PARTITION p2001q2 VALUES LESS THAN (2452092),
        PARTITION p2001q3 VALUES LESS THAN (2452184),
        PARTITION p2001q4 VALUES LESS THAN (2452276),
        PARTITION p2002q1 VALUES LESS THAN (2452366),
        PARTITION p2002q2 VALUES LESS THAN (2452457),
        PARTITION p2002q3 VALUES LESS THAN (2452549),
        PARTITION p2002q4 VALUES LESS THAN (2452641),
        PARTITION pmax VALUES LESS THAN (MAXVALUE))
CLUSTERED BY (ss_item_sk) INTO 13 BUCKETS
STORED AS HOLODESK
WITH PERFORMANCE;

ii. 创建 store_returns 表,为其划分数据分区并指定分桶数量。

CREATE TABLE store_returns (
   sr_returned_date_sk         INTEGER,
   sr_return_time_sk             INTEGER,
   sr_item_sk                        INTEGER NOT NULL,
   sr_customer_sk                INTEGER,
   sr_cdemo_sk                    INTEGER,
   sr_hdemo_sk                   INTEGER,
   sr_addr_sk                       INTEGER,
   sr_store_sk                      INTEGER,
   sr_reason_sk                   INTEGER,
   sr_ticket_number            BIGINT NOT NULL,
   sr_return_quantity          INTEGER,
   sr_return_amt                 FLOAT,
   sr_return_tax                   FLOAT,
   sr_return_amt_inc_tax     FLOAT,
   sr_fee                              FLOAT,
   sr_return_ship_cost         FLOAT,
   sr_refunded_cash            FLOAT,
   sr_reversed_charge         FLOAT,
   sr_store_credit                FLOAT,
   sr_net_loss                      FLOAT
)
CLUSTERED BY (sr_item_sk) INTO 13 BUCKETS
STORED AS HOLODESK WITH PERFORMANCE;

7. 在业务低峰期依次执行下述命令,将 TXT 格式的外表数据写入至刚刚创建的分桶表中。

-- 开启数据动态写入,即写入时基于分区键的值自动将数据放置到对应分区中
set hive.exec.dynamic.partition=true;
set stargate.dynamic.partition.enabled=true;

-- 将数据写入 store_sales 表,该表已创建分区和分桶
INSERT INTO store_sales
PARTITION (ss_sold_date_sk)
SELECT
   ss_sold_time_sk,
   ss_item_sk,
   ss_customer_sk,
   ss_cdemo_sk,
   ss_hdemo_sk,
   ss_addr_sk,
   ss_store_sk,
   ss_promo_sk,
   ss_ticket_number,
   ss_quantity,
   ss_wholesale_cost,
   ss_list_price,
   ss_sales_price,
   ss_ext_discount_amt,
   ss_ext_sales_price,
   ss_ext_wholesale_cost,
   ss_ext_list_price,
   ss_ext_tax,
   ss_coupon_amt,
   ss_net_paid,
   ss_net_paid_inc_tax,
   ss_net_profit,
   ss_sold_date_sk
FROM tpcds_text_100.store_sales;

-- 将数据写入 store_returns 表
INSERT INTO TABLE store_returns
SELECT
   sr_returned_date_sk,
   sr_return_time_sk,
   sr_item_sk,
   sr_customer_sk,
   sr_cdemo_sk,
   sr_hdemo_sk,
   sr_addr_sk,
   sr_store_sk,
   sr_reason_sk,
   sr_ticket_number,
   sr_return_quantity,
   sr_return_amt,
   sr_return_tax,
   sr_return_amt_inc_tax,
   sr_fee,
   sr_return_ship_cost,
   sr_refunded_cash,
   sr_reversed_charge,
   sr_store_credit,sr_net_loss
FROM tpcds_text_100.store_returns;

提示:数据写入的执行时间由集群负载、数据规模等因素决定,您可以登录 DBA Service,在查询页面中查看任务执行进度。

8. (可选)数据导入执行完成后,通过 SELECT COUNT(*) 来确认这两个表的条目数是否与原表一致。

查询性能对比

为更好地展示分桶前后的性能对比,本案例使用的机器资源设定了一些的限制,因此查询响应时间仅供演示参考,真实业务场景中分区前的查询效率和速度会更高。

数据分桶前

接下来,我们回到 XYZ 公司的业务需求,来设计一个 SQL 查询语句。由于高退货率可能意味着商品的质量、描述、定价或其他相关因素存在问题,XYZ 公司的数据分析团队希望找出销量超过 100 的商品的退货率,列出退货率最高的10个商品的具体名称,为售后团队的决策提供数据支持。

提示:为了确保数据的准确性和可靠性,该查询只考虑那些销售数量超过 100 的商品,避免因销售数量较少的商品带来的极端退货率数据干扰分析结果。

在查询设计中,我们首先使用 CTE(公共表表达式)分别预先聚合商品的销量和退货量,然后在主查询中联接这两个数据集以计算退货率,即退货数除以销售数的百分比,同时该查询还与 item 表联接,以便获取每个商品的具体名称,最后,将查询结果按退货率降序排列,并只返回退货率最高的前 10 个商品,具体 SQL 语句如下:

WITH SalesData AS (
   SELECT
       ss.ss_item_sk AS item_key,
       COUNT(*) AS sales_count
   FROM
       store_sales ss
   GROUP BY
       ss.ss_item_sk
),
ReturnsData AS (
   SELECT
       sr.sr_item_sk AS item_key,
       COUNT(*) AS return_count
   FROM
       store_returns sr
   GROUP BY
       sr.sr_item_sk
)
SELECT
   s.item_key,
   i.i_product_name,
   s.sales_count,
   r.return_count,
   (CAST(r.return_count AS FLOAT) / s.sales_count) * 100 AS return_percentage
FROM
   SalesData s
JOIN
   ReturnsData r
   ON s.item_key = r.item_key
JOIN
   item i
   ON s.item_key = i.i_item_sk -- 连接 item 表以获取产品名称
WHERE
   s.sales_count > 100
ORDER BY
   return_percentage DESC
LIMIT 10;

在 Beeline 中执行上述语句,等待查询执行完成,命令行将返回查询结果和耗时,具体如下:

image.png

本次查询耗时约为 37.18 秒,为了进一步了解查询任务在任务执行的各阶段的耗时情况,我们登录到 DBA Service 平台,在查询*页面找到并单击刚刚执行完成的查询作业,然后单击*调度阶段页签。

可以看到该查询任务被分为多个调度阶段,时间主要花费在了 ID 为 12954 和 12950 这 2 个调度阶段,在执行 Join 时,系统需要确保具有相同连接键的记录位于同一节点上,此时产生了大量的 Shuffle 读和写,如下图所示,Shuffle 读的数据量为 2 GB*,Shuffle 写的数据量为 2.5 GB,拖慢了整体的查询速度。

image.png

数据分桶后

而在对表执行数据分桶后,我们使用执行相同的查询,获得的查询结果和耗时如下:

image.png

本次查询仅耗时约 3.57 秒,相较于之前查询速度提升了 10 倍以上,同样登录至 DBA Service 平台,在查询页面找到并单击刚刚执行完成的查询作业,由于 store_sales 和 store_returns 采用相同的分桶键,JOIN 操作可以在各个节点上高效地局部进行,而无需跨节点传输数据。如下图所示,本次查询只产生了极少的 Shuffle 读写,极大地提升了数据查询效率,此外,相较于分桶前,还提升了任务的并行度,进一步发挥了分布式集群并发执行任务的优势。

image.png

除此以外,前面我们提到,为了满足按时间范围查询退货数据的需求,我们还对 store_sales 表进行了分区,当查询的过滤条件包含分区键时,我们还可以获得进一步的查询性能提升,从而让数据处理的范围进一步缩小,例如我们在前面 SQL 查询语句的基础上限定查询 2000 年的数据,具体如下:

WITH SalesData AS (
   SELECT
       ss.ss_item_sk AS item_key,
       COUNT(*) AS sales_count
   FROM
       store_sales ss
   WHERE
       ss.ss_sold_date_sk BETWEEN 2451545 AND 2451910 -- 限定查询时间范围
   GROUP BY
       ss.ss_item_sk
),
ReturnsData AS (
   SELECT
       sr.sr_item_sk AS item_key,
       COUNT(*) AS return_count
   FROM
       store_returns sr
   GROUP BY
       sr.sr_item_sk
)
SELECT
   s.item_key,
   i.i_product_name, -- 产品名称
   s.sales_count,
   r.return_count,
   (CAST(r.return_count AS FLOAT) / s.sales_count) * 100 AS return_percentage
FROM
   SalesData s
JOIN
   ReturnsData r
   ON s.item_key = r.item_key
JOIN
   item i
   ON s.item_key = i.i_item_sk -- 连接 item 表以获取产品名称
WHERE
   s.sales_count > 100 -- Sales threshold
ORDER BY
   return_percentage DESC
LIMIT 10;

等待查询执行完成,由于处理的数据范围可以通过分区快速定位,本次查询可以处理更少的数据,最终查询耗时约为 1.45 秒。

image.png

通过比较分桶前后的查询性能,我们可以看到:

  • 降低 Shuffle:本案例中,两个大的事实表采用相同的键分桶,连接和聚合操作可以在每个节点上独立执行,避免了数据在节点间的 shuffle,大大提高效率。
  • 提升任务并行度:选择合适的分桶可以确保数据在多个桶中均匀地分布,提升任务并行度。

此外,我们还结合了分区表的优势(减少数据扫描等特性)进一步优化了查询性能,充分利用它们的优势并实现最佳的性能。

相关文章:

【性能优化】表分桶实践最佳案例

分桶背景 随着企业的数据不断增长,数据的分布和访问模式变得越来越复杂。我们前面介绍了如何通过对表进行分区来提高查询效率,但对于某些特定的查询模式,特别是需要频繁地进行数据联接查或取样的场景,仍然可能面临性能瓶颈。此外…...

数据仓库的挑战

建设数据仓库是一个复杂且资源密集的过程,需要考虑多个方面。以下是建设数据仓库时常见的挑战及其详细解释: 1. 数据集成 挑战: 数据来源多样:数据来自不同的系统、数据库、文件格式(如CSV、JSON、XML)、…...

基于ResNet-18的简单分类(新手,而且网络效果不咋滴,就是学个流程)

引言 先看问题: 我手边有一数据集,然后我想分分类!~~ 咳咳,最近刚做了一个:训练集有1143张,分为5类,里面图片是打乱的。测试集有248张,想把它分分类看看咋样。 再看一下效果: …...

自动化测试:Autorunner的使用

自动化测试:Autorunner的使用 一、实验目的 1、掌握自动化测试脚本的概念。 2、初步掌握Autorunner的使用 二、Autorunner的简单使用 autoRunner使用方法 新建项目 a) 在项目管理器空白区域,右键鼠标,选择新建项目 b) 输入项目名后,点击[确定]. 在初次打开aut…...

时序预测 | Matlab基于CNN-BiLSTM-Attention多变量时间序列多步预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于CNN-BiLSTM-Attention多变量时间序列多步预测; 2.多变量时间序列数据集(负荷数据集),采用前96个时刻预测的特征和负荷数据预测未来96个时刻的负荷数据&…...

软考 系统架构设计师系列知识点之杂项集萃(42)

接前一篇文章:软考 系统架构设计师系列知识点之杂项集萃(41) 第67题 Windows操作系统在图形界面处理方面采用的核心架构风格是( )风格。Java语言宣传的“一次编写,到处运行”的特性,从架构风格…...

FastBoot刷机获取root权限(Magisk)

1.首先要下载ADB、Fastboot等工具。 1.ADB、Fastboot工具 https://developer.android.com/studio/releases/platform-tools 2.安装FastBoot的USB驱动 https://developer.android.com/studio/run/oem-usb 2.下载对应的镜像 https://developers.google.com/android/images?…...

信息检索(43):SPLADE: Sparse Lexical and Expansion Model for First Stage Ranking

SPLADE: Sparse Lexical and Expansion Model for First Stage Ranking 摘要1 引言2 相关工作3 方法3.1 SparTerm3.2 SPLADE:稀疏词汇和扩展模型 4 实验5 结论 发布时间(2021) 标题:稀疏词汇 扩展模型 摘要 稀疏的优点&#xf…...

DockerHub 镜像加速

Docker Hub 作为目前全球最大的容器镜像仓库,为开发者提供了丰富的资源。Docker Hub 是目前最大的容器镜像社区,DokcerHub的不能使用,导致在docker下pull镜像无法下载,安装kubernetes镜像也受到影响,下面请看解决方式。 1.加速原理 Docker下载加速的原理…...

Oracle 迁移 Mysql

-- Oracle->MySQL -- 使用时改一下where条件的owner和table_name -- 字段数据类型映射时会将Oracle中的浮点NUMBER转换为decimal(65,8)定点数 -- 可以识别主键约束、非空约束,但无法识别外键约束、唯一约束、自定义check -- 对于Oracle字符串长度为4000的&#x…...

vue3父子组件通信

一&#xff0c;父传子——defineProps 方法&#xff1a; 在父组件的模板中使用子组件标签&#xff0c;并且给标签自定义属性和属性名&#xff0c;即通过v-bind绑定数值&#xff0c;而后传给子组件&#xff1b;子组件则通过defineProps接收使用。 父组件&#xff1a; <tem…...

CSS中使用应用在伪元素中的计数器属性counter-increment

在CSS中&#xff0c;counter-increment 是一个用于递增计数器值的属性。它通常与 counter-reset 和 content 属性一起使用&#xff0c;以在文档中的特定位置&#xff08;如列表项、标题等&#xff09;插入自动生成的数字或符号。 counter-increment 基本用法&#xff1a; 使…...

【SkiaSharp绘图08】SKPaint方法:自动换行、是否乱码、字符偏移、边界、截距、文本轮廓、测量文本

文章目录 SKPaint方法BreakText 计算指定宽度内可绘制的字符个数ContainsGlyphs字体是否包含文本字符(是否会乱码)GetGlyphOffsets 字符偏移量GetGlyphPositions 偏移坐标GetGlyphWidths 每个字符的宽度与边界GetHorizontalTextIntercepts 轮廓截距GetPositionedTextIntercepts…...

深入理解Servlet Filter及其限流实践

引言 在Java Servlet技术中&#xff0c;Filter是一个拦截器&#xff0c;它允许开发者在请求到达目标资源之前或响应发送给客户端之后&#xff0c;对请求或响应进行拦截和处理。这种机制为实现诸如身份验证、日志记录、请求修改等功能提供了极大的灵活性。 Filter基础 Filter…...

使用cv2对视频指定区域进行去噪

视频去噪其实和图象一样&#xff0c;只是需要现将视频截成图片&#xff0c;在对图片进行去噪&#xff0c;将去噪的图片在合成视频就行。可以利用cv2.imread()、imwrite()等轻松实现。 去噪步骤 1、视频逐帧读成图片 2、图片指定区域批量去噪 2、去噪后的图片写入视频 1、视频逐…...

AI在创造还是毁掉音乐?

AI对音乐产业的影响是复杂而多维的&#xff0c;既有创造性的贡献也存在潜在的挑战。我们可以从以下几个角度来分析这个问题&#xff1a; ### 创造性贡献 1. **音乐创作**&#xff1a;AI可以帮助音乐家创作新的旋律和和声&#xff0c;甚至生成完整的音乐作品。例如&#xff0c…...

【2023年全国青少年信息素养大赛智能算法挑战赛复赛真题卷】

目录 2023全国青少年信息素养大赛智能算法挑战赛初中组复赛真题 2023全国⻘少年信息素养⼤赛智能算法挑战复赛⼩学组真题 2023全国青少年信息素养大赛智能算法挑战赛初中组复赛真题 1. 修复机器人的对话词库错误 【题目描述】 基于人工智能技术的智能陪伴机器人的语言词库被…...

Android系统揭秘(一)-Activity启动流程(上)

public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread (IApplicationThread) contextThread; … try { … int result …...

使用Java实现哈夫曼编码

前言 哈夫曼编码是一种经典的无损数据压缩算法&#xff0c;它通过赋予出现频率较高的字符较短的编码&#xff0c;出现频率较低的字符较长的编码&#xff0c;从而实现压缩效果。这篇博客将详细讲解如何使用Java实现哈夫曼编码&#xff0c;包括哈夫曼编码的原理、具体实现步骤以…...

IDEA、PyCharm等基于IntelliJ平台的IDE汉化方式

PyCharm 或者 IDEA 等编辑器是比较常用的&#xff0c;默认是英文界面&#xff0c;有些同学用着不方便&#xff0c;想要汉化版本的&#xff0c;但官方没有这个设置项&#xff0c;不过可以通过插件的方式进行设置。 方式1&#xff1a;插件安装 1、打开设置 File->Settings&a…...

visual studio 创建c++项目

目录 环境准备&#xff1a;安装 visual studiovisual studio 创建c项目Tips&#xff1a;新建cpp文件注释与取消注释代码 其他初学者使用Visual Studio开发C和C时常遇到的3个坑 环境准备&#xff1a;安装 visual studio 官网&#xff1a;https://visualstudio.microsoft.com/zh…...

MGV电源维修KUKA机器人电源模块PH2003-4840

MGV电源维修 库卡电源模块维修 机器人电源模块维修 库卡控制器维修 KUKA电源维修 库卡机器人KUKA主机维修 KUKA驱动器模块维修 机械行业维修&#xff1a;西门子系统、法那克系统、沙迪克、FIDIA、天田、阿玛达、友嘉、大宇系统&#xff1b;数控冲床、剪板机、折弯机等品牌数控…...

设置浏览器互不干扰

目录 一、查看浏览器文件路径 二、 其他盘新建文件夹Cache 三、以管理员运行CMD 四、执行命令 一、查看浏览器文件路径 chrome://version/ 二、 其他盘新建文件夹Cache D:\chrome\Cache 三、以管理员运行CMD 四、执行命令 Mklink /d "C:\Users\Lenovo\AppData\Loca…...

kafka操作命令详解

目录 1、集群运维命令 1.1、集群启停命令 1.3、集群迁移命令 1.4、权限管理命令 1.4.1、权限参数介绍 1.4.2、增加权限命令 1.4.3、移出权限命令 1.4.4、查看所有topic权限命令 1.4.5、查看某个topic权限命令 2、生产者命令 2.1、创建topic命令 2.2、删除topic命令 …...

graalvm jdk和openjdk

下载地址:https://github.com/graalvm/graalvm-ce-builds/releases 官网: https://www.graalvm.org...

docker基础使用教程

1.准备工作 例子&#xff1a;工程在docker_test 生成requirements.txt文件命令&#xff1a;&#xff08;使用参考链接2&#xff09; pip list --formatfreeze > requirements.txt 参考链接1&#xff1a; 安装pipreqs可能比较困难 python 项目自动生成环境配置文件require…...

计算机网络 交换机的安全配置

一、理论知识 1.交换机端口安全功能介绍 交换机端口安全功能是针对交换机端口进行安全属性的配置&#xff0c;以控制用户的安全接入。主要包括以下两种配置项&#xff1a; ①限制交换机端口的最大连接数&#xff1a;控制交换机端口连接的主机数量&#xff1b;防止用户进行恶…...

深入解析大语言模型系列:Transformer架构的原理与应用

引言 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;近几年取得了突破性的进展&#xff0c;而 Transformer 作为这些模型的核心架构&#xff0c;功不可没。本文将详细介绍 Transformer 的原理、结…...

uni-app地图组件控制

uni.createMapContext(mapId,this) 创建并返回 map 上下文 mapContext 对象。在自定义组件下&#xff0c;第二个参数传入组件实例this&#xff0c;以操作组件内 <map> 组件。 注意&#xff1a;uni.createMapContext(mapId, this) app-nvue 平台 2.2.5 支持 uni.create…...

前端调用api发请求常用的请求头content- type的类型和常用场景

Content-Type 是一个非常重要的HTTP头&#xff0c;它定义了发送给服务器或客户端的数据的MIME类型。这对于服务器和客户端正确解析和处理数据至关重要。下面是一些常见的 Content-Type 值及其用途和区别。 常见的 Content-Type 值 text/plain • 用途: 纯文本&#xff0c;无格…...

数据仓库之SparkSQL

Apache Spark SQL是Spark中的一个组件&#xff0c;专门用于结构化数据处理。它提供了通过SQL和DataFrame API来执行结构化数据查询的功能。以下是对Spark SQL的详细介绍&#xff1a; 核心概念 DataFrame: 定义: DataFrame是一个分布式数据集合&#xff0c;类似于关系型数据库中…...

如何在 MySQL 中导入和导出数据库以及重置 root 密码

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 如何导入和导出数据库 导出 要导出数据库&#xff0c;打开终端&#xff0c;确保你没有登录到 MySQL 中&#xff0c;然后输入以下命令&…...

基于uni-app和图鸟UI的云课堂小程序开发实践

摘要&#xff1a; 随着移动互联网的快速发展&#xff0c;移动学习已成为教育领域的重要趋势。本文介绍了基于uni-app和图鸟UI框架开发的云课堂小程序&#xff0c;该小程序实现了移动教学、移动学习、移动阅读和移动社交的完美结合&#xff0c;为用户提供了一个便捷、高效的学习…...

解决python从TD数据库取50w以上大量数据慢的问题

1.问题背景描述 python项目中的时序数据都存放在TD数据库中&#xff0c;数据是秒级存入的&#xff0c;当查询一周数据时将超过50w数据量&#xff0c;这是一次性获取全量数据到python程序很慢&#xff0c;全流程10秒以上&#xff0c;希望进行优化加速 2.排查 首先&#xff0c…...

游戏心理学Day21

玩家情绪与暴力攻击 情绪 情绪的分类 情绪是一种经常波动的东西&#xff0c;我们既体验过骄傲激动和开心&#xff0c;也体验过羞怯内疚和沮丧。我们的感受高度依赖于情境。研究者区分出至少三种途径来考察作为一种相对固定的人格特征的情绪&#xff0c;即为情感性&#xff0…...

接口测试基础 --- 什么是接口测试及其测试流程?

接口测试是软件测试中的一个重要部分&#xff0c;它主要用于验证和评估不同软件组件之间的通信和交互。接口测试的目标是确保不同的系统、模块或组件能够相互连接并正常工作。 接口测试流程可以分为以下几个步骤&#xff1a; 1.需求分析&#xff1a;首先&#xff0c;需要仔细…...

贪心+动归1

​​​​​​​​​​​​​​跳跃游戏 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0…...

三星S20以上手机中的动态相片及其分解

三星S20以后的相机&#xff0c;相机拍出来的图片&#xff0c;用三星手机自带的“相册”打开之后&#xff0c;还会有“查看动态照片”的选项&#xff0c;点击之后就能查看拍照片时前后2秒左右的视频&#xff01; 不知道这个功能是不是三星独有的。 这样得到的图片非常大。因为…...

一文了解HarmonyOSNEXT发布重点内容

华为在2024年6月21日的开发者大会上正式发布了HarmonyOS NEXT版&#xff0c;这是华为在操作系统领域的一次重大飞跃&#xff0c;标志着华为在构建全场景智能生态方面的卓越成就。HarmonyOS NEXT版不仅带来了全新的系统架构和性能提升&#xff0c;还首次将AI能力融入系统&#x…...

矩阵中严格递增的单元格数

题目链接&#xff1a;leetcode:矩阵中严格递增的单元格数 描述 给你一个下标从 1 开始、大小为 m x n 的整数矩阵 mat&#xff0c;你可以选择任一单元格作为 起始单元格 。 从起始单元格出发&#xff0c;你可以移动到 同一行或同一列 中的任何其他单元格&#xff0c;但前提是目…...

超参数调优-通用深度学习篇(上)

文章目录 深度学习超参数调优网格搜索示例一&#xff1a;网格搜索回归模型超参数示例二&#xff1a;Keras网格搜索 随机搜索贝叶斯搜索 超参数调优框架Optuna深度学习超参数优化框架nvidia nemo大模型超参数优化框架 参数调整理论&#xff1a; 黑盒优化&#xff1a;超参数优化…...

小程序中data-xx是用方式

data-sts"3" 是微信小程序中的一种数据绑定语法&#xff0c;用于在 WXML&#xff08;小程序模板&#xff09;中将自定义的数据绑定到页面元素上。让我详细解释一下&#xff1a; data-xx 的作用&#xff1a; data-xx 允许你在页面元素上自定义属性&#xff0c;以便在事…...

【2024德国工作】外国人在德国找工作是什么体验?

挺难的&#xff0c;德语应该是所有中国人的难点。大部分中国人进德国公司要么是做中国业务相关&#xff0c;要么是做技术领域的工程师。先讲讲人在中国怎么找德国的工作&#xff0c;顺便延申下&#xff0c;德国工作的真实体验&#xff0c;最后聊聊在今年的德国工作签证申请条件…...

Unity中获取数据的方法

Input和GetComponent 一、Input 1、Input类&#xff1a; 用于处理用户输入&#xff08;如键盘、鼠标、触摸等&#xff09;的静态类 2、作用&#xff1a; 允许你检查用户的输入状态。如某个键是否被按下&#xff0c;鼠标的位置&#xff0c;触摸的坐标等 3、实例 (1) 键盘…...

Java的死锁问题

Java中的死锁问题是指两个或多个线程互相持有对方所需的资源&#xff0c;导致它们在等待对方释放资源时永久地阻塞的情况。 死锁产生条件 死锁发生通常需要满足以下四个必要条件&#xff1a; 互斥条件&#xff1a;至少有一个资源是只能被一个线程持有的&#xff0c;如果其他…...

Unity 公用函数整理【二】

1、在规定时间时间内将一个值变化到另一个值&#xff0c;使用Mathf.Lerp实现 private float timer;[Tooltip("当前温度")]private float curTemp;[Tooltip("开始温度")]private float startTemp 20;private float maxTemp 100;/// <summary>/// 升…...

千年古城的味蕾传奇-平凉锅盔

在甘肃平凉这片古老而神秘的土地上&#xff0c;有一种美食历经岁月的洗礼&#xff0c;依然散发着独特的魅力&#xff0c;那便是平凉锅盔。平凉锅盔&#xff0c;那可是甘肃平凉的一张美食名片。它外表金黄&#xff0c;厚实饱满&#xff0c;就像一轮散发着诱人香气的金黄月亮。甘…...

微信小程序视频如何下载

一、工具准备 1、抓包工具Fiddler Download Fiddler Web Debugging Tool for Free by Telerik 2、VLC media player Download official VLC media player for Windows - VideoLAN 3、微信PC端 微信 Windows 版 二、开始抓包 1、打开Fiddler工具&#xff0c;设置修改如下…...

SVN 安装教程

SVN 安装教程 SVN&#xff08;Subversion&#xff09;是一个开源的版本控制系统&#xff0c;广泛用于软件开发和文档管理。本文将详细介绍如何在不同的操作系统上安装SVN&#xff0c;包括Windows、macOS和Linux。 Windows系统上的SVN安装 1. 下载SVN 访问SVN官方网站或Visu…...

HTML静态网页成品作业(HTML+CSS)—— 家乡山西介绍网页(3个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有6个页面。 二、作品演示 三、代…...