Hive实战进阶:从核心概念到性能优化的完整避坑指南
1. 从入门到力竭Hive实战避坑与进阶指南最近在数据仓库项目中深度使用Hive从环境搭建到复杂SQL调优一路踩坑无数真可谓“玩Hive玩到力竭”。很多朋友在初次接触Hive时往往被其“类SQL”的友好外表迷惑忽略了其背后基于Hadoop MapReduce的执行引擎特性导致在开发和生产中频频遇到性能瓶颈、诡异报错和配置难题。本文将系统梳理Hive从入门到进阶的核心知识体系结合实战中高频出现的“坑点”提供一套完整的解决方案。无论你是刚接触大数据的新手还是正在为Hive作业效率头疼的开发者都能从中找到清晰的路径和实用的技巧。2. Hive核心概念与架构解析为什么它既是SQL又是MapReduce在深入实战之前必须理解Hive的本质。Hive并非一个传统的关系型数据库而是一个构建在Hadoop之上的数据仓库工具。它将结构化的数据文件映射为一张数据库表并提供了一套HiveQLHQL查询语言该语言在底层会被转换为MapReduce、Tez或Spark任务执行。2.1 Hive的架构组成一个典型的Hive架构包含以下核心组件用户接口CLI命令行、JDBC/ODBC、WebUI如Hue。元数据存储Metastore这是Hive的“大脑”通常使用独立的RDBMS如MySQL、PostgreSQL存储表名、列、分区信息、表类型等元数据。这是第一个易错点很多人误以为数据存在Metastore里其实它只存结构信息。驱动器Driver包含编译器、优化器和执行器负责将HQL转换为执行计划。执行引擎早期默认是MapReduce现在Tez和Spark因其更优的性能成为主流选择。HadoopHDFS用于存储实际数据YARN用于资源管理和调度。2.2 Hive表数据的物理存储理解这一点至关重要Hive中的表本质上是HDFS目录表中的数据是目录下的文件。创建表时指定的LOCATION就是HDFS路径。这种“元数据与数据分离”的架构使得Hive具备极高的灵活性但也带来了数据一致性需要手动维护的挑战。3. 环境准备与版本选择避开版本兼容的“天坑”“玩到力竭”的起点往往是环境。版本不兼容是Hive学习路上最大的拦路虎。3.1 核心组件版本匹配建议以下是一个经过验证的相对稳定的组合以Apache社区版为例Hadoop: 3.x (如 3.3.6)Hive: 3.x (如 3.1.3)。注意Hive 4.x (如4.2.0) 改动较大对Hadoop和JDK版本要求更高初学者建议从3.x稳定版开始。Java: JDK 8 或 JDK 11需与Hadoop、Hive版本匹配Hive 3.1.x通常兼容JDK 8。Metastore数据库: MySQL 5.7 或 PostgreSQL。关键避坑点务必查阅你所用Hive版本官方文档的“Requirements”部分确认与其他组件的精确版本对应关系。盲目安装最新版极易导致各种ClassNotFoundException或连接失败。3.2 快速搭建使用Docker Compose一键部署对于学习和测试手动搭建HadoopHive集群极其繁琐。推荐使用Docker快速构建隔离环境。以下docker-compose.yml示例可搭建一个包含Hadoop、Hive和MySQL Metastore的简易环境。version: 3.8 services: namenode: image: bde2020/hadoop-namenode:2.0.0-hadoop3.2.1-java8 container_name: namenode ports: - 9870:9870 # Web UI - 8020:8020 # HDFS environment: - CLUSTER_NAMEtest volumes: - namenode_data:/hadoop/dfs/name datanode: image: bde2020/hadoop-datanode:2.0.0-hadoop3.2.1-java8 container_name: datanode depends_on: - namenode environment: - CORE_CONF_fs_defaultFShdfs://namenode:8020 volumes: - datanode_data:/hadoop/dfs/data hive-metastore: image: bde2020/hive:2.3.2-postgresql-metastore container_name: hive-metastore depends_on: - namenode environment: - SERVICE_NAMEhivemetastore - DB_DRIVERpostgres ports: - 9083:9083 hive-server: image: bde2020/hive:2.3.2-hive container_name: hive-server depends_on: - hive-metastore - namenode environment: - SERVICE_NAMEhiveserver2 - HIVE_CORE_CONF_javax_jdo_option_ConnectionURLjdbc:postgresql://hive-metastore/metastore ports: - 10000:10000 # HiveServer2 volumes: namenode_data: datanode_data:使用命令docker-compose up -d启动后可以通过docker exec -it hive-server /bin/bash进入容器使用beeline -u jdbc:hive2://localhost:10000连接Hive。4. Hive SQL基础与核心操作实战HiveQL与标准SQL高度相似但有其特有的扩展。掌握以下操作是基础中的基础。4.1 数据库与表操作-- 1. 创建数据库并指定在HDFS的存储位置 CREATE DATABASE IF NOT EXISTS mydb COMMENT 我的测试数据库 LOCATION /user/hive/warehouse/mydb.db; USE mydb; -- 2. 创建内部表Managed TableHive管理其生命周期删除表时数据也会被删除。 CREATE TABLE IF NOT EXISTS employee_internal ( id INT COMMENT 员工ID, name STRING COMMENT 员工姓名, salary FLOAT COMMENT 薪资, department STRING COMMENT 部门 ) COMMENT 员工信息表内部表 ROW FORMAT DELIMITED FIELDS TERMINATED BY , -- 指定字段分隔符为逗号 STORED AS TEXTFILE; -- 指定存储格式为文本文件 -- 3. 创建外部表External Table仅管理元数据删除表时数据文件不会被删除。常用于已有数据文件。 CREATE EXTERNAL TABLE IF NOT EXISTS employee_external ( id INT, name STRING, salary FLOAT, department STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY , STORED AS TEXTFILE LOCATION /user/data/employee; -- 指向已存在的HDFS路径 -- 4. 查看表详细信息 DESCRIBE FORMATTED employee_internal;4.2 数据加载与查询-- 准备本地数据文件 employee.txt -- 内容示例 -- 1,张三,8500.5,技术部 -- 2,李四,9200.0,市场部 -- 3,王五,7800.0,技术部 -- 1. 从本地文件系统加载数据到内部表复制文件 LOAD DATA LOCAL INPATH /opt/data/employee.txt OVERWRITE INTO TABLE employee_internal; -- 2. 从HDFS加载数据移动文件 -- LOAD DATA INPATH /user/input/employee.txt INTO TABLE employee_internal; -- 3. 基础查询 SELECT * FROM employee_internal WHERE department 技术部; -- 4. 聚合查询与分组 SELECT department, COUNT(*) as emp_count, AVG(salary) as avg_salary FROM employee_internal GROUP BY department HAVING avg_salary 8000; -- 5. 多表JOIN CREATE TABLE department_info (dept_name STRING, location STRING); INSERT INTO department_info VALUES (技术部, 北京), (市场部, 上海); SELECT e.name, e.salary, d.location FROM employee_internal e JOIN department_info d ON e.department d.dept_name;5. 高级特性与性能优化从“能用”到“好用”这是区分Hive新手和老手的关键。很多性能问题都源于对这些特性的不了解或误用。5.1 分区与分桶大幅提升查询效率的利器分区Partitioning根据某一列的值如日期、地区将表数据分布到不同的HDFS子目录中。查询时通过WHERE条件指定分区可以避免全表扫描。-- 创建分区表按日期分区 CREATE TABLE logs ( ip STRING, url STRING, duration INT ) PARTITIONED BY (dt STRING) -- 分区字段 ROW FORMAT DELIMITED FIELDS TERMINATED BY \t; -- 向特定分区加载数据 LOAD DATA LOCAL INPATH /opt/data/log_20231001.txt INTO TABLE logs PARTITION (dt2023-10-01); LOAD DATA LOCAL INPATH /opt/data/log_20231002.txt INTO TABLE logs PARTITION (dt2023-10-02); -- 查询时指定分区效率极高 SELECT * FROM logs WHERE dt2023-10-01;分桶Bucketing在分区内或全表范围内根据某列的哈希值将数据分成多个文件。适用于数据抽样、Map-Side JOIN优化。CREATE TABLE user_bucketed ( user_id INT, name STRING ) CLUSTERED BY (user_id) INTO 4 BUCKETS -- 根据user_id哈希分到4个桶 STORED AS ORC;5.2 文件存储格式ORC与Parquet文本格式TEXTFILE可读性好但性能差。生产环境强烈推荐使用列式存储格式。ORCHive原生高性能格式支持压缩、索引和谓词下推查询效率极高。Parquet与Spark生态兼容性更好跨平台优势明显。-- 创建ORC格式表 CREATE TABLE employee_orc ( id INT, name STRING, salary FLOAT ) STORED AS ORC TBLPROPERTIES (orc.compressSNAPPY); -- 使用Snappy压缩 -- 从文本表插入数据到ORC表 INSERT OVERWRITE TABLE employee_orc SELECT * FROM employee_internal;5.3 数据模型全量表、增量表与拉链表这是数据仓库设计的核心概念。全量表存储某个主题的完整数据每次更新都覆盖整个表。TRUNCATE INSERT模式。增量表只存储新增和变化的数据通常有一个时间戳字段。每天一个分区。拉链表记录数据在整个生命周期中所有状态的变化。包含start_date和end_date可以查询任何历史时间点的数据快照。这是实现“缓慢变化维SCD”的常用方法。拉链表示例-- 创建拉链表 CREATE TABLE user_zip ( user_id INT, name STRING, phone STRING, start_date STRING, end_date STRING ); -- 假设2023-10-01的初始数据 INSERT INTO user_zip VALUES (1, 张三, 13800138000, 2023-10-01, 9999-12-31), (2, 李四, 13900139000, 2023-10-01, 9999-12-31); -- 2023-10-02李四电话更新张三无变化 -- 步骤1将变化的旧记录失效李四 INSERT OVERWRITE TABLE user_zip SELECT user_id, name, phone, start_date, CASE WHEN user_id 2 THEN 2023-10-01 ELSE end_date END AS end_date -- 李四旧记录结束 FROM user_zip WHERE end_date9999-12-31; -- 步骤2插入新记录李四新记录张三不变记录 INSERT INTO TABLE user_zip SELECT 1, 张三, 13800138000, 2023-10-01, 9999-12-31 -- 张三不变 UNION ALL SELECT 2, 李四, 13900139001, 2023-10-02, 9999-12-31; -- 李四新记录查询2023-10-01的历史状态SELECT * FROM user_zip WHERE start_date 2023-10-01 AND end_date 2023-10-01;6. 自定义函数与HiveQL高级语法6.1 创建UDF永久函数Hive内置函数不够用时需要自定义UDF。编写Java类package com.example.hive.udf; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; public class UpperCaseUDF extends UDF { public Text evaluate(Text input) { if (input null) return null; return new Text(input.toString().toUpperCase()); } }打包成JARmvn clean package生成my-udf.jar。上传JAR到HDFShdfs dfs -put my-udf.jar /user/hive/jars/在Hive中创建永久函数-- 将JAR文件添加到Hive的classpath永久 CREATE FUNCTION my_upper AS com.example.hive.udf.UpperCaseUDF USING JAR hdfs:///user/hive/jars/my-udf.jar; -- 使用自定义函数 SELECT my_upper(name) FROM employee_internal;注意永久函数信息存储在Metastore中重启Hive服务后依然存在。6.2 窗口函数与QUALIFY子句窗口函数是进行复杂分析查询的利器。Hive 2.0 支持丰富的窗口函数。-- 为每个部门的员工按薪资排名 SELECT department, name, salary, ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) as rank_in_dept, AVG(salary) OVER (PARTITION BY department) as dept_avg_salary FROM employee_internal; -- Hive 2.1.0 引入了QUALIFY子句用于过滤窗口函数的结果比写子查询更简洁 SELECT department, name, salary, rank_in_dept FROM ( SELECT department, name, salary, ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) as rank_in_dept FROM employee_internal ) t WHERE rank_in_dept 2; -- 传统写法子查询过滤 -- 使用QUALIFY简化 SELECT department, name, salary, ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) as rank_in_dept FROM employee_internal QUALIFY rank_in_dept 2; -- 直接过滤更清晰7. 常见问题与故障排查清单以下是实战中高频出现的错误及解决方案。问题现象可能原因排查思路与解决方案FAILED: SemanticException [Error 10072]: Database does not exist1. 数据库名拼写错误。2. 未先创建数据库。1. 使用SHOW DATABASES;确认数据库是否存在。2. 使用CREATE DATABASE IF NOT EXISTS db_name;创建。FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTaskMapReduce任务执行失败原因非常广泛。1. 查看YARN ResourceManager WebUI获取具体任务错误日志。2. 检查输入数据路径是否存在、格式是否正确。3. 检查Hive表字段与数据文件分隔符是否匹配。4. 检查集群资源是否充足。MetaException(message:Got exception: org.apache.hadoop.ipc.RemoteException)Metastore服务连接失败。1. 确认Metastore服务是否启动netstat -tlnp | grep 9083。2. 检查hive-site.xml中javax.jdo.option.ConnectionURL等配置是否正确。3. 确认MySQL等数据库服务正常且用户有权限。查询速度极慢长时间无结果1. 未使用分区或分区过滤条件无效。2. 数据倾斜某个Key的数据量远大于其他。3. 存储格式为低效的TEXTFILE。4. 未开启向量化执行或Tez引擎。1. 使用EXPLAIN查看执行计划确认是否扫描了全表。2. 对JOIN或GROUP BY的大Key考虑加盐或使用skew join优化。3. 将表转换为ORC/Parquet格式。4. 设置set hive.vectorized.execution.enabledtrue;和set hive.execution.enginetez;。LOAD DATA成功但SELECT无数据1. 表字段分隔符与文件实际分隔符不匹配。2. 数据文件编码问题如UTF-8带BOM。3. 数据被加载到了错误的分区。1. 使用DESCRIBE FORMATTED table_name确认分隔符用cat命令查看文件前几行。2. 使用hexdump检查文件开头是否有EF BB BF等BOM标记。3. 检查分区目录hdfs dfs -ls /user/hive/warehouse/table_name。ClassNotFoundException或NoClassDefFoundError1. UDF的JAR包未正确添加到Hive会话或集群。2. Hive与Hadoop版本不兼容。1. 对于临时UDF使用ADD JAR对于永久UDF确保JAR在HDFS且路径正确。2. 统一所有组件的版本尤其是Hadoop、Hive和Tez/Spark。8. 生产环境最佳实践与工程建议统一配置管理将hive-site.xml中的通用优化参数如执行引擎、压缩格式、动态分区模式固化避免每次会话手动设置。SQL编写规范始终指定分区字段在查询条件中显式指定分区避免全分区扫描。避免SELECT *只选择需要的列特别是列式存储下性能提升明显。尽早过滤数据将WHERE条件中能过滤大量数据的条件提前或使用子查询先过滤。注意JOIN顺序将小表放在JOIN的左边Hive默认会将最后一个表作为流式表。使用EXPLAIN和ANALYZE在提交复杂SQL前使用EXPLAIN查看执行计划使用ANALYZE TABLE table_name COMPUTE STATISTICS收集表统计信息帮助CBO成本优化器做出更好的决策。监控与调优关注YARN ApplicationMaster日志和Hive Server日志。针对数据倾斜可使用set hive.groupby.skewindatatrue;或手动拆分大Key。合理设置Map和Reduce任务数量set mapred.reduce.tasks10;。数据生命周期管理为分区表建立归档和清理策略例如使用脚本自动删除N天前的旧分区释放HDFS存储空间。权限与安全在生产环境结合Sentry或Ranger对Hive数据库、表和列进行细粒度的权限控制避免误操作和数据泄露。Hive的学习曲线前期平缓后期陡峭。从会写HQL到写出高性能的HQL从能跑通任务到能稳定高效地管理数仓需要大量的实践和踩坑。希望本文梳理的这条从核心概念、环境搭建、基础操作、高级特性到排错优化的路径能帮你系统性地掌握Hive少走弯路最终从“力竭”走向“游刃有余”。真正的精通源于对每一个细节背后原理的探究和对每一次异常问题的彻底解决。

相关新闻

【 Figure F.03人形机器人技术解析】完全自主爬梯如何跨越真实世界移动门槛

【 Figure F.03人形机器人技术解析】完全自主爬梯如何跨越真实世界移动门槛

文章目录Figure F.03人形机器人技术解析:完全自主爬梯如何跨越真实世界移动门槛一、引言:机器人终于开始迁就人的世界二、事件与证据边界:视频证明了什么2.1 三层信息必须分开2.2 一段视频尚未回答的关键问题三、为什么爬梯比跑跳更难3.1 从连…

2026/10/13 13:38:09 阅读更多 →
秋招不仅是拼技术:软件测试面试中,这3个软技能比代码更重要

秋招不仅是拼技术:软件测试面试中,这3个软技能比代码更重要

关注 「软件测试就业联盟」公众号,陪你走好校招求职的每一步 秋招季一到,团队分给我十几个校招面试名额,面到现在最大的感受就是:大家的八股文背得越来越溜,算法题刷得越来越猛,可一到那种“没标准答案”的…

2026/10/11 18:36:02 阅读更多 →
Python类变量与实例变量详解及实践指南

Python类变量与实例变量详解及实践指南

1. 从实际案例理解类变量与实例变量第一次接触Python面向对象编程时,很多人都会被类变量和实例变量搞得晕头转向。我清楚地记得自己早期写的一个电商系统库存管理类时犯过的错误:class Product:total_inventory 0 # 类变量def __init__(self, name, st…

2026/10/5 16:17:38 阅读更多 →

最新新闻

GRP-U8行政事业版数据库部署与运维:从选型到备份恢复的实战指南

GRP-U8行政事业版数据库部署与运维:从选型到备份恢复的实战指南

简介:无论是日常余额核对、凭证追溯,还是年末结转时清理数据,面对GRP-U8行政事业版庞大的数据库常常让人无从下手。这份资料面向用友GRP-U8财务软件的运维实施与行政事业单位信息化人员,集中梳理出真正核心的四张业务表——GL_Yeb…

2026/10/13 22:59:15 阅读更多 →
Servlet从原理到实战:吃透Java Web底层核心机制

Servlet从原理到实战:吃透Java Web底层核心机制

Servlet 这门技术,放在十年前是 Java Web 开发者的必修课,放在今天看,很多刚接触 Spring Boot 的同学可能只在依赖清单里见过它,甚至有人觉得它已经过时了。但实际上去掉 Spring 的外壳,真正在底层处理 HTTP 请求、管理…

2026/10/13 22:59:15 阅读更多 →
ThinkPHP新闻发布系统开发实战:从路由到后台管理全流程

ThinkPHP新闻发布系统开发实战:从路由到后台管理全流程

简介:ThinkPHP新闻发布系统是一份面向PHP初学者和Web开发入门者的完整前后台项目源码,覆盖前台文章展示、后台分类与文章管理,并集成百度UEditor富文本编辑器,旨在通过一个真实项目帮助理解MVC分层、ActiveRecord数据库操作、路由…

2026/10/13 22:59:15 阅读更多 →
Servlet核心机制与生命周期详解:从HTTP请求到Java方法的完整链路

Servlet核心机制与生命周期详解:从HTTP请求到Java方法的完整链路

Servlet这东西,说起来有点“老”,但如果你想搞明白Java Web到底是怎么跑起来的,它还真躲不开。我带团队和面试新人的时候发现一个现象:不少人上来就学Spring Boot,写接口已经非常熟练,但你把问题往回问一层…

2026/10/13 22:59:15 阅读更多 →
Java NIO Channel深度解析:从BIO痛点、Buffer机制到非阻塞实战

Java NIO Channel深度解析:从BIO痛点、Buffer机制到非阻塞实战

1. 从BIO的痛点到Channel的设计动机很多同学学NIO的时候,一上来就啃Selector、ByteBuffer、Channel这三大件,结果学完一圈还是不知道Channel到底解决了什么问题。我刚开始接触NIO那会儿也是这样,API背得滚瓜烂熟,真到写网络服务的…

2026/10/13 22:59:15 阅读更多 →
ACM竞赛中STL sort的cmp函数设计原理与避坑指南

ACM竞赛中STL sort的cmp函数设计原理与避坑指南

1. 为什么排序不是“写个for循环就完事”的事?刚接触ACM竞赛的新人,十有八九都经历过这个阶段:看到一道题说“把数组从小到大排好”,立刻撸起袖子写个冒泡——三重嵌套,i、j、k变量齐飞,跑样例能过&#xf…

2026/10/13 22:58:14 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →