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

MySQL学习笔记09:MySQL高级特性深度学习(上):count函数、数据类型与分库分表核心原理

📅 学习日期:2025年10月10日
学习时长:1小时
🎯 学习方式:苏格拉底式对话教学
📝 博客性质:真实学习过程记录


在这里插入图片描述

📖 前言

这篇博客记录了我学习MySQL高级特性的完整思考过程。不同于传统的技术博客,这里记录了我的每一个疑问、每一次思考、每一个"啊哈"时刻。

本文涵盖:

  • count函数的性能差异
  • 数据类型选择的实战思考
  • 分库分表的核心原理
  • B+树结构深度剖析
  • 分片键选择策略
  • 跨分片查询优化

学习方式:苏格拉底式提问,通过问答逐步深入理解每个知识点。


📑 目录

  1. count函数深度理解
  2. 数据类型选择实战
  3. 分库分表核心原理
  4. B+树结构回顾
  5. 分片键选择策略
  6. 跨分片查询优化
  7. 总结与反思

📊 第一部分:count函数深度理解

场景引入

在学习MySQL统计函数时,我遇到了一个看似简单但实则复杂的问题:

CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(50),email VARCHAR(100),age INT
);

这几种count有什么区别?

SELECT count(*) FROM users;
SELECT count(1) FROM users;
SELECT count(id) FROM users;
SELECT count(email) FROM users;

我的初步理解

我最初的认知

“查询所有不同的结果,只要有不同的字段就统计,count字段名的话就是单纯看某个字段,如果出现NULL就不统计。”

但是我发现这个理解不够准确,于是开始深入研究每种写法的具体行为。


深入思考:count(字段名)

为了验证我的理解,我构造了测试数据:

id | name  | email
1  | John  | john@qq.com
2  | Lisa  | NULL
3  | Tom   | tom@qq.com
4  | Jerry | NULL

我的推测

  • count(*)返回:4行
  • count(1)返回:4行
  • count(email)返回:2行(因为有2个NULL)

实际验证结果:✅ 推测完全正确!


核心疑问:count(*) vs count(1)

既然count(*)和count(1)都返回4,那它们有什么区别?哪个更快?

我的第一直觉:count(1)应该更快,因为1是常量,不需要访问字段。

我的推理

“count(1)的话执行器不需要其他东西,只看行数。count(*)也不看其他内容,统计行数,但是它可能需要处理列信息,会有额外开销。”


真相揭晓:我错了!

通过查阅MySQL官方文档和实测EXPLAIN,我发现:两者性能完全相同!

原理解析

MySQL优化器做了特殊优化:

count(*) → 优化器识别 → 转换为"统计行数"操作
count(1) → 优化器识别 → 转换为"统计行数"操作

执行计划对比

EXPLAIN SELECT count(*) FROM users;
EXPLAIN SELECT count(1) FROM users;
-- 两者的执行计划完全相同!

底层实现

  • InnoDB会选择最小的索引来扫描
  • 不会真的去读取每一行的所有字段
  • 只统计行的存在性

性能对比

count(*) ≈ count(1) > count(主键) > count(非主键字段)

为什么count(email)最慢?

  • 需要判断每一行的email字段是否为NULL
  • 需要读取email字段的值
  • 额外的判断开销

我的理解纠正

最初我有个错误理解:我以为count(email)是判断email是否相同。

后来我意识到:不是判断是否相同,而是判断是否为NULL!

正确理解

  • count(字段):统计非NULL的记录数
  • 不是统计不同的值,那是count(DISTINCT 字段)

关键区别

count(email)          -- 统计非NULL的email数量(结果:2)
count(DISTINCT email) -- 统计不同email的数量(结果:2,john@qq.com和tom@qq.com)

性能对比总结

count函数性能对比
count星号/count1
count主键
count非主键字段
最快 - 扫描最小索引
较快 - 扫描主键索引
最慢 - 需判断NULL

🎯 第二部分:数据类型选择实战

场景1:用户ID的数据类型选择

在设计用户系统时,我首先遇到一个基础问题:用户ID应该选择什么数据类型?

候选方案

  • A. INT(32位,最大约21亿)
  • B. BIGINT(64位,最大约922京)
  • C. VARCHAR

我的第一直觉

“VARCHAR吧,字符占内存小,因为用户id本身不会很大,所以varchar够了还能动态控制”


我的认知错误

在实际对比后,我发现这个想法完全错了!

实际存储对比

  • INT:固定4字节
  • VARCHAR(‘123456’):6字节内容 + 1-2字节长度 = 7-8字节

我的顿悟

“确实不能这样,应该用INT。如果数据量明确会超过int范围就用BIGINT。INT是32位,2的32次方个数,大概是几亿?”

准确计算

  • INT:-21亿 到 +21亿(2^31)
  • UNSIGNED INT:0 到 42亿(2^32)
< 10万
10万-1000万
1000万-1亿
1亿-10亿
> 10亿
用户ID类型选择
预估用户量
INT足够
INT足够
INT足够留余地
考虑BIGINT
必须BIGINT

场景2:超大规模系统的ID选择

思考更深一层:微信、抖音这样的超大规模系统,用户量可能达到几十亿,应该用什么类型?

系统规模对比

小型系统(几万用户):  INT够用
中型系统(几百万用户):INT够用
大型系统(几千万用户):INT够用(留有余地)
超大系统(几亿用户):  INT接近上限
顶级系统(几十亿用户):BIGINT必须

我查阅了实际数据

  • 微信:超过12亿用户 → 必须BIGINT
  • 抖音:超过10亿用户 → 必须BIGINT
  • 淘宝:超过8亿用户 → BIGINT

我的思考

“微信每秒活跃用户几百万,那个数字感觉很庞大。小型系统不用BIGINT,但中大型系统必须用。”

设计原则总结

  • 预估未来3-5年的数据量
  • 留有足够的冗余空间
  • 数据类型一旦确定,很难修改(涉及大量数据迁移)

场景3:金额字段的数据类型选择

在电商系统中存储商品价格时,我又遇到了一个坑。

候选方案

  • A. FLOAT(单精度浮点)
  • B. DECIMAL(10,2)(定点数)
  • C. INT(存储分)

我的第一直觉

“DECIMAL可能丢失精度吧,但是一般到分也就够了,我觉得是B”

但我错了!恰恰相反!


金额存储的精度陷阱

精度对比

-- FLOAT的精度问题
CREATE TABLE test_float (price FLOAT);
INSERT INTO test_float VALUES (123.456);
SELECT * FROM test_float;
-- 结果:123.456001831055  ← 精度丢失!-- DECIMAL的精确存储
CREATE TABLE test_decimal (price DECIMAL(10,2));
INSERT INTO test_decimal VALUES (123.45);
SELECT * FROM test_decimal;
-- 结果:123.45  ← 完全精确!-- INT存分的方式
CREATE TABLE test_int (price INT COMMENT '单位:分');
INSERT INTO test_int VALUES (12345);  -- 表示123.45元
SELECT price / 100 AS yuan FROM test_int;
-- 结果:123.45  ← 精确且节省空间!

我的理解纠正

“原来小数类型(FLOAT/DOUBLE)反而会丢失精度!我是惯性思维了,C++中float转int会精度丢失,但这里情况恰好相反。”

金额存储决策树

必须精确到分
可接受微小误差
高性能
可读性优先
金额存储方案
精度要求
性能要求
FLOAT/DOUBLE不推荐
INT存分
DECIMAL10,2
推荐方案
备选方案

最佳实践

金额字段选择:
1. 首选:INT(存储分) → 最节省空间,完全精确
2. 备选:DECIMAL(10,2) → 可读性好,精确
3. 禁用:FLOAT/DOUBLE → 精度不可控,容易出错

数据类型选择总结

场景推荐类型原因
用户IDINT / BIGINT定长,性能高,节省空间
商品价格INT(存分) / DECIMAL精确存储,避免精度丢失
用户名VARCHAR变长,节省空间
手机号CHAR(11) / BIGINT定长11位,CHAR或数字存储
邮箱VARCHAR(100)长度不定,需要变长
创建时间DATETIME / TIMESTAMP根据时区需求选择

🚀 第三部分:分库分表核心原理

引入场景:电商订单表的性能瓶颈

在学习过程中,我思考了一个实际场景:

假设我负责一个电商平台的订单系统:

CREATE TABLE orders (id BIGINT PRIMARY KEY,user_id INT,product_id INT,amount DECIMAL(10,2),status VARCHAR(20),created_at DATETIME,INDEX(user_id),     -- 有索引!INDEX(created_at)   -- 也有索引!
);

数据增长情况

第1年:1000万订单
第2年:5000万订单
第3年:1.5亿订单
第4年:3亿订单  ← 现在

用户抱怨

  • “查询我的订单怎么这么慢?”
  • “下单按钮点了半天没反应!”

我的初步分析

用EXPLAIN分析查询,发现扫描了几百万行数据!

我的第一反应

“user_id上没有索引导致全表扫描”

但仔细看表结构:有INDEX(user_id)啊!

我的困惑:索引都有了,为什么还慢?


问题的真相:即使有索引也慢!

我开始从更深层次分析问题:

线索1:B+树高度增加

1000万数据:B+树高度约3层
1亿数据:  B+树高度约4层
3亿数据:  B+树高度约4-5层  ← 现在

每多一层,就多一次磁盘IO!

线索2:服务器资源到极限

单台MySQL服务器:
- CPU: 16核,已经100%了
- 内存: 64GB,Buffer Pool不够用
- 磁盘IO: 每秒10000次读写,已到上限
- 网络带宽: 1Gbps,高峰期打满

线索3:业务压力

每秒新增订单:5000条
每秒查询请求:50000次

我的顿悟

“大量的磁盘IO,数据量过大,服务器顶不住!”

问题本质:即使有索引,根本问题是架构设计的瓶颈

3亿订单单表
问题1: 索引树过高
问题2: Buffer Pool装不下
问题3: 磁盘IO到上限
问题4: CPU100%
解决方案: 分库分表

解决方案:水平扩展

如果我是架构师,我会怎么解决?

方案对比

  • 垂直扩展(升级服务器):治标不治本,成本高
  • 水平扩展(多台服务器):根本解决方案

我的思考

“水平扩展吧,效率高且方便,负载均衡,打到每台机子的数据量小一点,每个上面存个三层。四层二十多亿可能会直接爆掉服务器。”

我的核心疑问

“关键这些机子咋平衡呢?全部放一个机房还是分散?会不会多一层代理分发的时间?查询时咋知道要到具体哪台机子上查?

这就是分库分表的核心难题!


核心难题:数据如何分配?

假设:我们有4台MySQL服务器

方案A:随机分配

订单1 → 随机选服务器1
订单2 → 随机选服务器3
订单3 → 随机选服务器2

问题:查询user_id=123456的所有订单时,需要查询4台服务器!


方案B:按订单ID取模

订单id % 4 = 0 → 服务器1
订单id % 4 = 1 → 服务器2
订单id % 4 = 2 → 服务器3
订单id % 4 = 3 → 服务器4

问题:查询user_id=123456的所有订单时,还是需要查询4台服务器!


方案C:按user_id取模

user_id % 4 = 0 → 服务器1
user_id % 4 = 1 → 服务器2
user_id % 4 = 2 → 服务器3
user_id % 4 = 3 → 服务器4

优势:查询user_id=123456的所有订单时,只需要查询1台服务器!

我的选择

“C方案吧,按user_id分,最好几台机子间耦合性低一些,效率高”

✅ 这就是"分片键选择"的核心原则!

查询user_id=123456
计算: 123456 % 4 = 0
路由到服务器1
只查询1台服务器
方案A/B随机或按订单ID
需要查询4台服务器
性能差

分片键选择原则

通过思考,我总结出了核心原则:

1. 根据最频繁的查询选择分片键
2. 让相关数据在同一个分片
3. 避免跨分片查询

电商订单系统的查询分析

-- 查询1:用户查看自己的订单(高频)
SELECT * FROM orders WHERE user_id = 123456;
→ 按user_id分片:只查1台服务器 ✅-- 查询2:按订单ID查询(中频)
SELECT * FROM orders WHERE id = 888888;
→ 按user_id分片:不知道在哪台服务器 ❌-- 查询3:按时间范围查询(低频)
SELECT * FROM orders WHERE created_at BETWEEN '2025-01-01' AND '2025-01-31';
→ 按user_id分片:需要查4台服务器 ❌

我的思考

“按频率高低划分服务优先级以及快慢,用户查看自己订单需要最快,那么可以就按user_id一级分片;id查询中频,也需要快速满足,那么可以将热点id缓存实现高频数据快速访问,二级分片再结合具体需要比如create_at来二级分片查询;时间查询响应速度可以慢一些,为了节省缓存资源这些就不用把它放缓存,user_id和create_at都有索引,可以联合索引稍微优化,且between本身就是范围查询,速度不会很慢”

✅ 完美的架构思维!


优化方案总结

三层优化策略

【第1层:分片策略】
├─ 一级分片:user_id(满足高频查询)
└─ 二级分片:created_at(分散热点数据)【第2层:缓存策略】
├─ 热点订单ID → Redis(中频查询加速)
└─ 热点用户数据 → Redis(高频查询加速)【第3层:索引优化】
├─ 联合索引(user_id, created_at)
└─ 时间范围查询用索引(可接受的慢查询)

这就是真实生产环境的架构方案!


🌳 第四部分:B+树结构深度回顾

我的疑问:二级索引为什么会到5层?

在分析性能问题时,我看到有人提到"二级索引可能到5层",感到困惑。

我的疑问

“二级索引为什么会到5层?B+树不是3-4层吗?”


二级索引的回表过程

查询示例

SELECT * FROM orders WHERE user_id = 123456;

完整过程

步骤1:走user_id二级索引树(4层)

第1层(根节点):   在内存中(Buffer Pool) → 0次IO
第2层:            可能在内存中 → 0次IO
第3层:            可能需要磁盘读取 → 1次IO
第4层(叶子节点): 需要磁盘读取 → 1次IO

叶子节点存储内容

[user_id=123456, 主键id=100]
[user_id=123456, 主键id=500]
[user_id=123456, 主键id=1200]
...
[user_id=123456, 主键id=9999]  ← 假设有100条

找到了100个主键id!


步骤2:回表查询(100次!)

对每个主键id,都要走一次主键索引树(4层):

查询 id=100:第1层(根节点): 在内存 → 0次IO第2层:          可能在内存 → 0次IO第3层:          磁盘读取 → 1次IO第4层(叶子节点):磁盘读取 → 1次IO → 找到完整数据查询 id=500:... 重复上述过程... (重复100次)

总IO次数

理想情况:2(二级索引)+ 100×2(回表)= 202次IO
最坏情况:4(二级索引)+ 100×4(回表)= 404次IO

我的疑惑

“为啥二级索引只需要4次IO,回表这里就要100次?正常IO次数是多少?”

我查资料后理解了

  • 二级索引:走一次索引树,找到100个主键id(4次IO)
  • 回表:每个主键id都要走一次主键索引树(100 × 4次IO)
  • 正常IO次数:主键查询2-4次IO,二级索引查询可能上百次IO

二级索引查询流程图

查询二级索引树user_id主键索引树1. WHERE user_id=1234562. 扫描索引树(4次IO)3. 返回100个主键id4. 根据主键id查询5. 扫描主键树(4次IO)6. 返回完整数据loop[回表100次]总IO: 4 + 100×4 = 404次查询二级索引树user_id主键索引树

B+树结构细节回顾

我的疑问

“这个索引树咋会这么高呢,我有点忘记结构了,一般不是三层吗,第二层放索引,第三层放数据,大概二十一万数据还是多少忘了”


B+树结构图

双向链表
双向链表
双向链表
根节点
10, 20, 30
非叶子节点
3, 5, 8
非叶子节点
12, 15, 18
非叶子节点
22, 25, 28
非叶子节点
32, 35, 38
叶子节点
id=1,user_id=100...
叶子节点
id=5,user_id=105...
叶子节点
id=15,user_id=115...
叶子节点
id=18,user_id=118...

每层能存多少数据?

假设:

  • 每个数据页大小 = 16KB(InnoDB默认)
  • 每个索引指针 = 6字节
  • 每个键值(主键BIGINT)= 8字节

第1层(根节点)

16KB ÷ (8字节键 + 6字节指针) ≈ 1170 个指针
→ 能指向1170个第2层节点

第2层(非叶子节点)

1170个节点 × 每个节点1170个指针 ≈ 136万 个指针
→ 能指向136万个第3层节点(叶子节点)

第3层(叶子节点)

假设每条数据1KB
16KB ÷ 1KB ≈ 16条数据/页136万个叶子节点 × 16条 ≈ 2176万条数据

我的记忆

“那确实不能这样,应该用int,如果数据量明确会超过int范围就用bigint,int32位,2的三十二次方个数,大概是几亿?”

正确!3层约2100万数据,4层约24.5亿数据!


B+树查找过程

我的疑问

“每一层是咋走下去的,三层都是纯索引键值吗还有啥,为啥能走下去”


详细查找过程:WHERE id = 15

步骤1:读取根节点

比较:15在 10~20 之间
→ 走指针2

步骤2:读取第2层某个节点

比较:15在 12~18 之间
→ 走对应指针

步骤3:到达叶子节点

→ 找到id=15的完整数据

每个节点存的内容

非叶子节点

[指针 | 键值 | 指针 | 键值 | 指针 | 键值 | 指针]
  • 键值:用于比较范围(如10, 20, 30)
  • 指针:指向下一层节点的磁盘地址(页号)

叶子节点

[完整数据行1][完整数据行2][完整数据行3]...
  • 主键索引:叶子节点存完整行数据
  • 二级索引:叶子节点存索引列+主键值

🎯 第五部分:订单ID设计方案

问题:按订单ID查询怎么办?

按user_id分片后,如果按订单ID查询,不知道在哪台服务器,怎么办?

解决方案:在订单ID里嵌入分片信息!


雪花算法(Snowflake ID)改进版

传统雪花算法

【64位订单ID】
┌─────────┬─────────┬─────────┬─────────┐
│ 41位时间戳 │ 10位机器ID │ 12位序列号 │ 1位符号位 │
└─────────┴─────────┴─────────┴─────────┘

改进版:嵌入分片信息

【64位订单ID】
┌─────────┬──────┬─────────┬─────────┐
│ 41位时间戳 │ 4位分片ID │ 6位机器ID │ 12位序列号 │
└─────────┴──────┴─────────┴─────────┘↑这里!

查询流程

SELECT * FROM orders WHERE id = 1234567890123456;

步骤

1. 从ID中提取分片ID = (订单ID >> 18) & 0xF
2. 计算出分片ID = 3
3. 直接去第3号服务器查询
4. 在该服务器上用主键索引查询 → 2-4次IO ✅

这样按ID查询也很快了!


🔧 第六部分:完整架构设计

我的架构思考

我的完整方案

“按频率高低划分服务优先级以及快慢,用户查看自己订单需要最快,那么可以就按user_id一级分片;id查询中频,也需要快速满足,那么可以将热点id缓存实现高频数据快速访问(1,2查询都会加快),二级分片再结合具体需要比如create_at来二级分片查询;时间查询响应速度可以慢一些,为了节省缓存资源这些就不用把它放缓存,user_id和create_at都有索引,可以联合索引稍微优化,且between本身就是范围查询,速度不会很慢”


完整架构图

user_id % 8 = 0
user_id % 8 = 1
user_id % 8 = 7
缓存命中
缓存未命中
用户请求
应用层路由
分片键判断
分片1
分片2
分片8...
主库 - 写
从库1 - 读
从库2 - 读
主库 - 写
从库1 - 读
Redis缓存层
直接返回

三层优化策略详解

第1层:分片策略

├─ 一级分片:user_id % 8
│   └─ 目标:让同一用户的订单在同一分片
├─ 二级分片:created_at(年月)
│   └─ 目标:分散热点数据,历史数据归档
└─ 订单ID嵌入分片信息└─ 目标:支持按ID快速定位

第2层:缓存策略

├─ 热点订单缓存
│   ├─ Key: order:{order_id}
│   ├─ TTL: 1小时
│   └─ 命中率目标:90%
│
└─ 热点用户缓存├─ Key: user_orders:{user_id}├─ TTL: 30分钟└─ 存储:最近20条订单

第3层:索引优化

├─ 主键索引:id(聚簇索引)
├─ 二级索引:user_id
├─ 联合索引:(user_id, created_at)
│   └─ 用于用户订单列表+时间筛选
└─ 二级索引:status└─ 用于状态筛选(待支付、已完成等)

数据迁移和扩容方案

我的思考

“数据迁移定期维护一下吧,如果迁移就停服维护将所有数据迁移?热点数据的话定期分散一下我觉得也可以,特殊化处理?”

查阅资料后,我发现有更好的方案

方案A:停服迁移(简单但不可取)

1. 停止服务
2. 数据迁移
3. 验证数据
4. 重启服务

问题:不能停服!


方案B:双写迁移(生产环境方案)

步骤1:新老系统同时写写订单时 → 同时写到4台服务器和8台服务器步骤2:后台迁移老数据慢慢把4台服务器的老数据迁移到8台步骤3:切换读流量逐步把读请求切到8台服务器步骤4:下线老系统迁移完成,删除4台服务器

📚 总结与反思

今天学到的核心知识点

1. count函数的本质

  • count(*) ≈ count(1):统计行数,性能相同
  • count(字段):统计非NULL值,需要判断,性能较差
  • MySQL优化器会自动选择最小索引扫描

2. 数据类型选择的实战思维

  • ID字段:INT(40亿内)/ BIGINT(超大规模)
  • 金额字段:INT(存分,精确且节省)/ DECIMAL(可读性好)
  • 字符字段:VARCHAR(变长)/ CHAR(定长)
  • 核心原则:预估数据量、精确度要求、存储效率

3. 分库分表的架构思维

  • 问题本质:单表数据量过大 → 性能下降 → 架构瓶颈
  • 解决方案:水平扩展 → 分片存储 → 路由查询
  • 核心难题:如何选择分片键?如何路由查询?
  • 设计原则:按最高频查询选择分片键

4. B+树结构深度理解

  • 3层B+树:约2100万数据
  • 4层B+树:约24.5亿数据
  • 二级索引回表:可能产生大量IO
  • 优化思路:覆盖索引、联合索引

5. 完整架构设计能力

  • 分片策略:一级分片 + 二级分片
  • 缓存策略:热点数据缓存
  • 索引优化:联合索引、覆盖索引
  • 核心思维:按查询频率分层优化

我的成长与感悟

1. 从单一角度到系统思维

  • 最初:只考虑索引优化
  • 现在:考虑分片、缓存、索引的完整方案
  • 收获:架构设计需要多层优化策略

2. 从理论到实战应用

  • 最初:知道B+树结构
  • 现在:理解IO次数、回表成本、性能瓶颈
  • 收获:理论要结合实际场景理解

3. 从被动接受到主动思考

  • 最初:被动回答问题
  • 现在:主动提出架构方案
  • 收获:苏格拉底式教学让我深度思考

4. 从局部优化到全局设计

  • 最初:优化单个SQL
  • 现在:设计完整的分库分表方案
  • 收获:架构师思维需要全局视角

待深入学习的内容(下篇预告)

1. 一致性Hash扩容方案

  • 如何优雅地从4台扩容到8台?
  • 如何减少数据迁移量?

2. 分布式事务处理

  • 跨分片的订单如何保证一致性?
  • 2PC、TCC、Saga方案对比

3. 主从复制原理

  • binlog、relay log的作用
  • 主从延迟如何处理?

4. 读写分离实现

  • 如何将读请求分发到从库?
  • 主从延迟对业务的影响

5. 生产环境最佳实践

  • 事务隔离级别选择
  • 配置参数调优
  • 监控和故障处理

面试准备

核心面试题

  1. count(*)和count(1)有什么区别?性能如何?
  2. 为什么金额字段不能用FLOAT?应该用什么?
  3. 什么是分库分表?如何选择分片键?
  4. 3层B+树能存多少数据?如何计算?
  5. 二级索引的回表过程是怎样的?如何优化?
  6. 如何设计一个支持亿级用户的订单系统?

答题思路

  • 从问题本质出发
  • 结合实际场景分析
  • 给出多种方案对比
  • 说明优缺点和适用场景
  • 展示架构设计思维

🎯 下篇预告

《MySQL高级特性深度学习(下):分库分表进阶与主从复制实战》

敬请期待! 🚀


📝 学习笔记
作者:[进击的圆儿]
日期:2025年10月10日
学习方式:苏格拉底式对话教学
目标:MySQL高级特性深度掌握,面试+实战双向准备

本文特色:记录真实学习过程,包含疑问、思考、纠正、顿悟的完整路径。
适合人群:MySQL进阶学习者、面试准备者、架构设计学习者


✨ 如果这篇博客对你有帮助,欢迎点赞、收藏、评论!

http://www.dtcms.com/a/466739.html

相关文章:

  • 失智老年人照护实训室建设指南:从意义到实践的全面解析
  • 10分钟上手OpenAI Agents SDK
  • 中文分析原始
  • JP4-8-MyLesson前台前端(二)
  • 做js题目的网站上海网站建设公司推荐排名
  • 网站建设效益分析代运营合同模板
  • 京东商品关键字搜索接口深度开发:从精准检索到商业机会挖掘的技术实现
  • 怎么看网站开发的发展wordpress能开发app
  • 项目学习总结:LVGL图形参数动态变化、开发板的GDB调试、sqlite3移植、MQTT协议、心跳包
  • 统一高效图像生成与编辑!百度新加坡国立提出Query-Kontext,多项任务“反杀”专用模型
  • 网站建设要那些东西适合个人开店的外贸平台
  • window安装wsl
  • 命题逻辑基础,形式系统,定理证明(二)
  • 如何利用数字源表进行纳米材料电特性表征?
  • 网络层协议之ICMP协议
  • 怎样做自己的网站钻钱宁波seo怎么选
  • skynet debug_console控制台中debug指令使用
  • 做棋盘游戏辅助的网站python和php做网站
  • 如何查看局域网内IP冲突问题?如何查看局域网IP环绕问题?arp -a命令如何使用?
  • 网站建设成都市南京做网站公司哪家好
  • 做电影视频网站赚钱嘛网站制作公司杭州
  • 建站平台哪个最好网站建设需要什么技术
  • 网页制作与网站建设实战大全pdf做网站的分辨率要多大
  • 主动学习:用“聪明提问”提升模型效率的迭代艺术
  • 数据链路层协议之MSTP协议
  • Debezium日常分享系列之:Debezium 3.3.0.Final发布
  • 网站的换肤功能怎么做哪个网站可以做验证码兼职
  • wordpress建站要钱吗中小型网站建设价格
  • gitee中的一些开源项目整理20251010
  • [JS]面试八股文