一条 SQL 慢了两周,最后查出两个根因:一个是 TCP 内存,一个是 4G 的 Metastore

一条 SQL 慢了两周,最后查出两个根因:一个是 TCP 内存,一个是 4G 的 Metastore

关键词:MetadataFetchFailedException、Spark shuffle 连接关闭、DataNode 1004 端口、CLOSE_WAIT 堆积、TCP out of memory、dfs.datanode.max.transfer.threads、sysctl tcp_mem、Hive Metastore JVM 调优、Kyuubi SQL 变慢

目录

  • 一、先说结论
  • [二、第一层:Kyuubi 说 SQL 失败了](#二、第一层:Kyuubi 说 SQL 失败了 "#%E4%BA%8C%E7%AC%AC%E4%B8%80%E5%B1%82kyuubi-%E8%AF%B4-sql-%E5%A4%B1%E8%B4%A5%E4%BA%86")
  • [三、第二层:Spark 说 shuffle 拿不到数据](#三、第二层:Spark 说 shuffle 拿不到数据 "#%E4%B8%89%E7%AC%AC%E4%BA%8C%E5%B1%82spark-%E8%AF%B4-shuffle-%E6%8B%BF%E4%B8%8D%E5%88%B0%E6%95%B0%E6%8D%AE")
  • 四、第三层:所有线索指向同一台机器
  • [五、第四层:那台机器的 1004 端口](#五、第四层:那台机器的 1004 端口 "#%E4%BA%94%E7%AC%AC%E5%9B%9B%E5%B1%82%E9%82%A3%E5%8F%B0%E6%9C%BA%E5%99%A8%E7%9A%84-1004-%E7%AB%AF%E5%8F%A3")
  • 六、第五层:线程栈里的真相
  • [七、第六层:内核日志中的 TCP out of memory](#七、第六层:内核日志中的 TCP out of memory "#%E4%B8%83%E7%AC%AC%E5%85%AD%E5%B1%82%E5%86%85%E6%A0%B8%E6%97%A5%E5%BF%97%E4%B8%AD%E7%9A%84-tcp-out-of-memory")
  • [八、一条被忽略的副线:Metastore 只有 4G](#八、一条被忽略的副线:Metastore 只有 4G "#%E5%85%AB%E4%B8%80%E6%9D%A1%E8%A2%AB%E5%BF%BD%E7%95%A5%E7%9A%84%E5%89%AF%E7%BA%BFmetastore-%E5%8F%AA%E6%9C%89-4g")
  • 九、第一次处理:回滚参数,无效
  • [十、转向内核:9 项 sysctl,缓解了](#十、转向内核:9 项 sysctl,缓解了 "#%E5%8D%81%E8%BD%AC%E5%90%91%E5%86%85%E6%A0%B89-%E9%A1%B9-sysctl%E7%BC%93%E8%A7%A3%E4%BA%86")
  • [十一、另一条线:Metastore 4G → 32G → 64G](#十一、另一条线:Metastore 4G → 32G → 64G "#%E5%8D%81%E4%B8%80%E5%8F%A6%E4%B8%80%E6%9D%A1%E7%BA%BFmetastore-4g--32g--64g")
  • 十二、完整因果链
  • 十三、复盘

一、先说结论

业务反馈:Kyuubi 上的 SQL 突然变慢,部分直接失败,任务频繁重试。

查了两周,最后发现问题不是"一个根因",而是两个独立的瓶颈,恰好同时发作:

sql 复制代码
阶段一:SQL 准备阶段  →  Hive Metastore,JVM 只有 4G
阶段二:SQL 执行阶段  →  某台 DataNode,TCP 内存耗尽

两者表现完全一样:

sql 复制代码
SQL 慢 / 超时 / 失败

但修法完全不同:

线 现象锚点 真正的解法
A. 网络栈 1004 端口 9677 个 CLOSE_WAIT、TCP: out of memory 批量调整 9 项内核参数
B. 元数据 Metastore 连接数 49--51、Kyuubi 会话 37--45 JVM 从 4G 扩到 32G,再到 64G

而中间有个很容易让人误判的插曲:

发现 dfs.datanode.max.transfer.threads 被调到 40960,回滚到 8192 并重启------问题依然存在。

这次失败的回滚,反而是整个排查的转折点。


二、第一层:Kyuubi 说 SQL 失败了

业务侧的报错很直接:

yaml 复制代码
Status: failed
org.apache.spark.shuffle.MetadataFetchFailedException:
Missing an output location for shuffle 1033 partition 5420

同时还有一类:

csharp 复制代码
Caused by: java.io.IOException:
Connection from dn-node-07/131.88.69.78:7337 closed

业务层面看到的是:

现象 频率
SQL 执行耗时显著增加 高
SQL 长时间无响应 中
SQL 直接失败 中
任务频繁重试 高
executor lost 中

第一反应通常是"Kyuubi 出问题了"。

但要注意:Kyuubi 只是 SQL 入口,它不做计算,只负责把 SQL 交给 Spark 引擎。

它报的错,多半是别人的错。


三、第二层:Spark 说 shuffle 拿不到数据

MetadataFetchFailedException 的含义很明确:

reduce task 去拉 shuffle 数据,但找不到某个 map output 的位置。

常见原因有八种:

kotlin 复制代码
① 生成 shuffle 数据的 executor 异常退出
② executor 所在节点不可用
③ Spark shuffle service 异常
④ 本地 shuffle 文件丢失
⑤ 节点磁盘异常或磁盘满
⑥ 网络连接异常
⑦ NodeManager 异常
⑧ external shuffle service 不稳定

八种可能,第一次看根本没法定位。

但第二条报错给了关键线索:

csharp 复制代码
Connection from dn-node-07/131.88.69.78:7337 closed

7337 是 shuffle 端口,而这台机器的名字,在报错里出现了不止一次。

所以不是"某个 executor 随机挂了",而是同一台机器上的 shuffle 服务不稳定。


四、第三层:所有线索指向同一台机器

把失败任务的 executor 分布拉出来,发现高度集中在一台节点上。

这台机器同时承担三个角色:

复制代码
DataNode         ------ 存数据
NodeManager      ------ 跑 YARN 容器
RegionServer     ------ 跑 HBase

再加上 NodeManager 内部的 Spark External Shuffle Service------一台机器上实际承载四类流量。

这是典型的混布节点。

混布本身没问题,但意味着:

这几个角色共享同一套 CPU、内存、磁盘、文件描述符、TCP 缓冲、网络带宽。 任何一方把资源吃光,其他人一起遭殃。

而且这台节点的 RegionServer 还在持续向同机的 DataNode 读 block------数据从本机磁盘出去,再从本机网卡走一趟,等于自己打自己。

于是去那台机器上看看。


五、第四层:那台机器的 1004 端口

第一个命令,数连接:

bash 复制代码
netstat -anp | grep 1004 | wc -l

结果:

yaml 复制代码
9000+

1004 是 HDFS DataNode 的数据传输端口。

继续看连接状态分布:

scss 复制代码
9677 CLOSE-WAIT
 259 ESTAB
   1 LISTEN
 121 TIME-WAIT

5.1 9677 个 CLOSE_WAIT 意味着什么

CLOSE_WAIT 的含义非常明确:

对端已经发了 FIN(我收到了关闭请求),但本机进程还没调 close()。

也就是说:

objectivec 复制代码
客户端已经走了
    ↓
DataNode 应该关掉 socket
    ↓
但它没关
    ↓
连接挂在 CLOSE_WAIT

9677 个------意味着近万个连接,客户端都走了,DataNode 还没处理完关闭动作。

5.2 这会带来什么连锁反应

层级 影响
socket 资源 每个连接占一个 fd,fd 被吃光
内存 每个 socket 有读写缓冲,占用内核内存
新连接 fd 满了、缓冲没了 → 新连接建不上
TCP 内存 大量 socket 缓冲累积 → 耗尽

而且要注意一点:

CLOSE_WAIT 是"被动等待",不是"正在传输"。 这些连接不干活,但依然占着资源。

这就是"假连接"------它们不产生吞吐,只消耗资源。


六、第五层:线程栈里的真相

光看连接数,只能知道"堵了",但不知道"为什么堵"。

抓线程栈:

arduino 复制代码
jcmd 34176 Thread.print > datanode_stack.txt

6.1 第一类:正在发数据的线程(RUNNABLE)

less 复制代码
"DataXceiver for client DFSClient_attempt_... at /10.0.x.x:31888
 [Sending block BP-...:blk_6600780846_...]"
java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.FileDispatcherImpl.size0(Native Method)
    at org.apache.hadoop.net.SocketOutputStream.transferToFully(SocketOutputStream.java:226)
    at org.apache.hadoop.hdfs.server.datanode.BlockSender.sendPacket(BlockSender.java:616)
    at org.apache.hadoop.hdfs.server.datanode.DataXceiver.readBlock(DataXceiver.java:611)

这些线程在正常干活 ------ 把 block 数据通过 socket 发出去。

6.2 第二类:卡在 SelectorPool 的线程(BLOCKED)

php 复制代码
"DataXceiver for client DFSClient_hb_rs_... at /10.0.x.x:35470
 [Sending block ...]"
java.lang.Thread.State: BLOCKED (on object monitor)
    at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(...)
    - waiting to lock <0x...> (a ConcurrentHashMap$Node)
    at org.apache.hadoop.net.SocketIOWithTimeout$SelectorPool.get(SocketIOWithTimeout.java:391)
    at org.apache.hadoop.net.SocketIOWithTimeout.waitForIO(SocketIOWithTimeout.java:244)
    at org.apache.hadoop.net.SocketOutputStream.waitForWritable(SocketOutputStream.java:171)

这一类的状态是 BLOCKED,不是 WAITING。

它们卡在两个地方:

arduino 复制代码
waitForWritable   ← 等 socket 可写(对端收不动)
SelectorPool.get  ← 抢 SelectorPool 里的 selector(锁竞争)

翻译成人话:

它们在等"对面能收下",而对面收不动;同时几百个线程在抢同一把 selector 锁。

6.3 一个容易误判的地方

DataXceiver.readBlock 出现在栈里,本身不是异常------正常节点读 block 也会有这条栈。

真正异常的是它伴随的状态:BLOCKED (on object monitor) + waiting to lock。

看线程栈不能只看"调用了什么方法",要看"线程处于什么状态"。 RUNNABLE 在发数据是正常的;BLOCKED 在抢锁才是问题。

6.4 客户端来源很杂

线程名里有两种 DFSClient:

复制代码
DFSClient_attempt_...   ← Spark / YARN 任务
DFSClient_hb_rs_...     ← HBase RegionServer

这台 DataNode 同时在服务 Spark 和 HBase。

所以它一卡,两边一起受影响------这正是混布带来的放大效应。


七、第六层:内核日志中的 TCP out of memory

再往下一层,看内核:

perl 复制代码
dmesg -T | grep -i "tcp"

大量出现:

sql 复制代码
TCP: out of memory -- consider tuning tcp_mem

7.1 这条日志意味着什么

socket 缓冲区占的是内核内存,不受 JVM 堆限制。

当 socket 数量太多、或者每个 socket 缓冲太大时:

复制代码
内核 TCP 内存限制(tcp_mem)被打满
    ↓
无法为新连接分配缓冲
    ↓
新连接建立失败 / 已有连接异常关闭

这是操作系统级的资源枯竭。

7.2 为什么它能直接导致 Spark 失败

perl 复制代码
TCP 内存耗尽
    ↓
新的 socket 分配不到缓冲
    ↓
Shuffle 连接(7337)建立失败或被重置
    ↓
MetadataFetchFailedException
    ↓
Kyuubi SQL 失败

主链路在这里闭合了:从 SQL 报错,一路追到内核。


八、一条被忽略的副线:Metastore 只有 4G

但如果问题到这里就"查清了",后面还会反复。

因为在同一时期的 Spark Driver 日志里,还有一组很不起眼的数据。

8.1 数据本身

arduino 复制代码
Spark Driver 频繁连接 thrift://metastore-host:[REDACTED_PORT_5]
​
Metastore 当前连接数     : 49 ~ 51
Kyuubi opening sessions  : 37 ~ 45

而查下去发现:

这台 Hive Metastore 的 JVM 堆,只有 4G。

8.2 4G 够不够

单看"4G 堆"好像还行------很多服务 4G 都能跑。

但 Metastore 的负载模型和普通服务不一样:

因素 说明
每个 Thrift 连接 占用线程栈 + 请求缓冲
每个元数据请求 拉 DBS / TBLS / PARTITIONS / PARTITION_KEY_VALS
分区裁剪 一次可能加载上万分区对象
并发 40+ 会话同时打,对象无法快速释放

一句话:Metastore 的堆压力,跟"分区数 × 并发会话数"直接相关。

8.3 它影响的是哪个阶段

这一点很关键------Metastore 慢,不会影响数据读写,它影响的是"准备阶段" :

sql 复制代码
SQL 解析
    ↓
元数据获取(表、列、分区)
    ↓
分区裁剪
    ↓
生成执行计划
    ↓
(以上都在 Metastore 侧完成)
    ↓
提交 Spark 作业 → 执行阶段(这里才是 DataNode / shuffle)

所以两条线的表现都是"SQL 慢",但一个慢在"开始之前",一个慢在"跑起来之后"。


九、第一次处理:回滚参数,无效

在主链路排查时,发现了一处配置改动:

xml 复制代码
<property>
    <name>dfs.datanode.max.transfer.threads</name>
    <value>40960</value>
    <!-- 原值 <value>8192</value> -->
</property>

从 8192 调到了 40960,翻了 5 倍。

9.1 为什么它看起来就是元凶

max.transfer.threads 控制 DataNode 允许的最大传输线程数(DataXceiver 上限)。

它本质是"闸门宽度",不是"处理能力"。

arduino 复制代码
底层能力 = min(磁盘 IO, 网络带宽, TCP 内存, fd 数量, CPU)
闸门宽度 = max.transfer.threads

底层已经是瓶颈时,把闸门开大,只会让更多线程涌进来一起堵住。

按这个推理,改回 8192 应该就缓解了。

9.2 我们改了,也重启了

xml 复制代码
<value>8192</value>

重启完成,DataNode 起来了。

然后再抓一次线程栈------

bash 复制代码
BLOCKED
waiting to lock
SocketIOWithTimeout$SelectorPool
SocketOutputStream.waitForWritable
DataXceiver.readBlock

一模一样。

参数回滚了,重启了,线程还是卡在同一个地方。

9.3 这次失败的回滚,价值很大

因为它排除了一整条假设:

arduino 复制代码
如果根因是"线程上限太高"
    ↓
回滚到 8192、重启、线程池重建
    ↓
应该恢复
    ↓
但事实是没有

结论:40960 不是根因,它只是一个"放大器"。

真正的瓶颈在更下层------内核的 TCP 缓冲、连接队列和回收能力。

继续在 DataNode 参数上折腾,是浪费时间。


十、转向内核:9 项 sysctl,缓解了

真正的处理发生在 6 月初。

判断是:高并发连接下,TCP 缓冲 / 队列 / 回收能力不足。

于是对整个 TDP 主机组做了一次批量内核参数调整。

10.1 先备份

css 复制代码
ansible all -m shell -a "cp /etc/sysctl.conf /etc/sysctl.conf_20260602"

10.2 用 lineinfile 保证幂等

(regexp 命中就覆盖,没有就追加------可重复执行,不会写重复行)

ini 复制代码
ansible all -m lineinfile -a "path=/etc/sysctl.conf regexp='^net.ipv4.tcp_mem\s*=' line='net.ipv4.tcp_mem = 2097152 3145728 4194304' state=present"
ansible all -m lineinfile -a "path=/etc/sysctl.conf regexp='^net.ipv4.tcp_rmem\s*=' line='net.ipv4.tcp_rmem = 4096 87380 16777216' state=present"
ansible all -m lineinfile -a "path=/etc/sysctl.conf regexp='^net.ipv4.tcp_wmem\s*=' line='net.ipv4.tcp_wmem = 4096 65536 16777216' state=present"
ansible all -m lineinfile -a "path=/etc/sysctl.conf regexp='^fs.file-max\s*=' line='fs.file-max = 2097152' state=present"
ansible all -m lineinfile -a "path=/etc/sysctl.conf regexp='^net.ipv4.tcp_max_orphans\s*=' line='net.ipv4.tcp_max_orphans = 262144' state=present"
ansible all -m lineinfile -a "path=/etc/sysctl.conf regexp='^net.ipv4.tcp_fin_timeout\s*=' line='net.ipv4.tcp_fin_timeout = 15' state=present"
ansible all -m lineinfile -a "path=/etc/sysctl.conf regexp='^net.ipv4.tcp_tw_reuse\s*=' line='net.ipv4.tcp_tw_reuse = 1' state=present"
ansible all -m lineinfile -a "path=/etc/sysctl.conf regexp='^net.core.somaxconn\s*=' line='net.core.somaxconn = 32768' state=present"
ansible all -m lineinfile -a "path=/etc/sysctl.conf regexp='^net.core.netdev_max_backlog\s*=' line='net.core.netdev_max_backlog = 16384' state=present"

10.3 生效并核验

css 复制代码
ansible all -m shell -a "sysctl -p /etc/sysctl.conf"
​
ansible all -m shell -a "sysctl net.ipv4.tcp_mem net.ipv4.tcp_rmem net.ipv4.tcp_wmem fs.file-max net.ipv4.tcp_max_orphans net.ipv4.tcp_fin_timeout net.ipv4.tcp_tw_reuse net.core.somaxconn net.core.netdev_max_backlog"

10.4 每一项在解决什么

参数 值 解决什么
net.ipv4.tcp_mem 2G / 3G / 4G(按页) 提高内核 TCP 内存总上限,消除 TCP: out of memory
net.ipv4.tcp_rmem 4096 / 87380 / 16M 放大接收缓冲上限,应对慢客户端
net.ipv4.tcp_wmem 4096 / 65536 / 16M 放大发送缓冲上限,缓解 waitForWritable 阻塞
fs.file-max 2097152 提高系统级 fd 上限
net.ipv4.tcp_max_orphans 262144 放宽半断开连接上限,避免被内核丢弃
net.ipv4.tcp_fin_timeout 15 缩短 FIN_WAIT_2 停留时间,加快回收
net.ipv4.tcp_tw_reuse 1 允许出方向复用 TIME_WAIT 连接
net.core.somaxconn 32768 加大 accept 队列,扛住瞬时建连
net.core.netdev_max_backlog 16384 加大网卡收包队列,避免丢包

10.5 结果

调整之后,症状明显缓解。

这里要强调一件事:

这次生效的不是"应用参数",是"内核参数"。

对比一下两次处理:

处理 层级 效果
40960 → 8192 应用(DataNode) 无效
9 项 sysctl 内核(TCP 栈) 有效

同一个人、同一个问题,把参数从"应用层"挪到"内核层",结果完全不同。


十一、另一条线:Metastore 4G → 32G → 64G

网络栈这条线缓解之后,剩下的"慢"还在。

原因就是第八章那条副线:Metastore 一直是 4G。

11.1 第一次扩容:4G → 32G

把 Metastore 的 JVM 堆从 4G 提到 32G ------8 倍。

这一步解决的是:

  • 大批量元数据请求时不再频繁 Full GC
  • 分区裁剪能装下更多分区对象
  • 40+ 并发会话下,对象分配不再紧张

11.2 第二次扩容:32G → 64G

后来又提到 64G。

为什么 32G 还不够?

因为它增长的不是"量",是"复杂度":

sql 复制代码
表数量 ↑
分区数量 ↑
并发会话数 ↑
每条 SQL 涉及的分区集合 ↑

这些都直接反映为 Metastore 堆里的对象数量。

元数据服务的堆,不是按"请求数"算的,是按"元数据规模 × 并发"算的。

11.3 两次扩容加起来是 16 倍

复制代码
4G  →  32G  →  64G
   8x       2x        合计 16x

一个跑了两年的 Metastore,配置从 4G 涨到 64G------这本身就说明了一件事:

元数据服务的容量,需要跟数据规模一起规划,而不是装完就不动了。


十二、完整因果链

现在可以把两条线拼在一起:

sql 复制代码
业务现象:SQL 慢 / 失败 / 重试
​
├─ 【线 B:准备阶段】
│    Hive Metastore JVM = 4G(严重偏小)
│            ↓
│    40+ 并发会话 × 大分区表元数据请求
│            ↓
│    GC 频繁 / 对象分配失败 / 响应变慢
│            ↓
│    SQL 解析、元数据获取、分区裁剪、计划生成变慢
│
└─ 【线 A:执行阶段】
     节点混布 DataNode + NodeManager + RegionServer
             ↓
     磁盘 93%--96%,block 读取慢
             ↓
     DataXceiver 发送 block 时下游收不动
             ↓
     线程 BLOCKED 在 waitForWritable + SelectorPool 锁
             ↓
     socket 不释放 → CLOSE_WAIT 累积到 9677
             ↓
     内核 TCP 内存耗尽:"TCP: out of memory"
             ↓
     同节点 Shuffle Service(7337)建连失败
             ↓
     MetadataFetchFailedException
             ↓
     SQL 失败
​
两条线在业务侧合流:
    "Kyuubi 上的 SQL 又慢又爱失败"

这就是为什么一开始会"查不清楚"------因为它们是两个独立的问题。


十三、复盘

13.1 七个判断

① "SQL 慢"要分阶段定位,不是分组件定位

一条 SQL 至少两个阶段:

复制代码
准备阶段:解析 → 元数据 → 分区裁剪 → 计划生成   (Metastore)
执行阶段:调度 → 读数据 → shuffle → 计算          (YARN / HDFS / 节点)

先判断它慢在哪一段,再去查那个段的组件。

判断方法:看 SQL 卡住时,Driver 日志在打什么------是在连 Metastore,还是在等 shuffle。

② 一个现象,可能是两个根因

如果一开始就认定"只有一个根因",要么会漏掉 Metastore,要么会漏掉 TCP。

排查到中期没有收敛,就该怀疑"是不是有两件事"。

③ 一次无效的回滚,比一次成功的修复更有信息量

把 40960 改回 8192、重启、问题依旧------这一步排除了一整条假设。

排查的本质不是"找到对的",是"排除错的"。 一个能被证伪的猜测,就是一个有价值的实验。

④ 同样的问题,换个层级就解决了

处理 层级 效果
max.transfer.threads 8192 应用 无效
9 项 sysctl 内核 有效

如果卡在应用层反复调参,说明瓶颈可能不在应用层。

判断信号:应用参数改完没效果,但内核日志里有告警。

⑤ CLOSE_WAIT 是"应用没关",不是"网络有问题"

它明确指向:对端已经关了,本机进程没有调 close()。

通常是应用层线程卡住,不是网络层故障。

⑥ 线程栈要看状态,不只看方法名

DataXceiver.readBlock 出现很正常;异常的是它伴随 BLOCKED。

方法名告诉你"它在做什么",状态告诉你"它卡在哪"。

⑦ 元数据服务的堆,要跟数据规模一起规划

4G → 32G → 64G,16 倍增长。

绝大多数"装完就不管"的 Metastore,都是在数据长到一定规模后才暴露容量问题。

判断标准:Metastore 堆大小,应该跟"分区总数 × 并发会话数"匹配,不是跟"平时 QPS"匹配。

13.2 排查 Checklist

执行阶段(DataNode / 网络)

检查项 命令
DataNode 端口连接数 `netstat -anp
连接状态分布 `ss -ant
CLOSE_WAIT 数量 `ss -ant state close-wait
线程栈 + 状态统计 jcmd <pid> Thread.print,`grep "Thread.State"
内核 TCP 告警 `dmesg -T
TCP 内存上限 cat /proc/sys/net/ipv4/tcp_mem
fd 使用 `lsof -p
max.transfer.threads hdfs getconf -confKey dfs.datanode.max.transfer.threads
磁盘水位 df -h /data*

准备阶段(Metastore)

检查项 命令
堆大小与使用 jcmd <pid> GC.heap_info、jstat -gcutil <pid> 1000 20
连接数 `ss -antp
元数据请求并发 Kyuubi opening sessions、Driver 侧 Metastore 连接数
分区规模 SELECT COUNT(*) FROM PARTITIONS;
慢查询 Metasotore 后端 MySQL 慢日志

最后一句

这两周最反直觉的地方是:

我们一直在找"那个根因",但它有两个。

一个在"SQL 开始之前",一个在"SQL 跑起来之后"。

而最接近真相的一刻,不是找到了什么,是否定了什么------

把 max.transfer.threads 改回 8192,重启,再抓一次栈,发现一模一样。

那一刻有点泄气。但也正是那一次,"DataNode 参数"这条线被彻底排除,方向才转向内核。

排查里最贵的动作,不是找到一个能解释现象的理论, 而是愿意花时间去验证它------哪怕结果可能是"我又错了"。

相关推荐
也非非也5 小时前
iPhone 中国区 AI 落地:Apple 与阿里千问合作的技术观察
大数据·人工智能·ios·agent·iphone·智子
CC数分6 小时前
统计学基础|先把问题问对:数据分析的六大类型
大数据·人工智能·算法
Elastic 中国社区官方博客6 小时前
基于 Elasticsearch 与 Jina AI 的全模态智能搜索实践:技术全解析
大数据·人工智能·elasticsearch·搜索引擎·ai·信息可视化·jina
RPAdaren6 小时前
财务机器人要怎么选?落地财务机器人时的常见问题有哪些?
大数据·人工智能·数据挖掘
众智鸿图6 小时前
XR驱动管网数据智能体检!众智鸿图精彩亮相2026燃气运营与安全研讨会
大数据·安全·xr
字节跳动数据平台6 小时前
火山引擎知识引擎 VeKnow|从企业本体到行动边界:Agent 能找到规则,为什么还是会判错?
大数据
财迅通Ai6 小时前
MLCC业务爆发式增长,带动昀冢科技三季度扭亏为盈
大数据·人工智能·科技·昀冢科技
PaperAccept7 小时前
【研知有术论文发表】材料科学一区期刊,影响因子30+的纳米科技SCI,审稿严格但有效率
大数据·数据结构·科技·量子计算
跨境卫士—小依7 小时前
TikTokShop旧版物流模板组件停用跨境技术团队如何完成系统迁移
大数据·人工智能·新媒体运营·跨境电商·跨境·营销策略