SQL性能调优:从执行计划看懂索引的使用与失效

SQL性能调优:从执行计划看懂索引的使用与失效

    • [📌 前言:调优的四个维度](#📌 前言:调优的四个维度)
    • 一、先看效果:索引的"降维打击"实验
      • [1.1 构建百万级测试数据](#1.1 构建百万级测试数据)
      • [1.2 主键查询 vs 无索引列查询](#1.2 主键查询 vs 无索引列查询)
      • [1.3 压测工具 `mysqlslap` 放大差距](#1.3 压测工具 mysqlslap 放大差距)
    • [二、调优核心利器:EXPLAIN 执行计划](#二、调优核心利器:EXPLAIN 执行计划)
      • [2.1 执行计划完整字段列表](#2.1 执行计划完整字段列表)
      • [2.2 `key_len` 精确计算法(高频面试计算题)](#2.2 key_len 精确计算法(高频面试计算题))
      • [2.3 `filtered` 与 `rows` 的联动计算](#2.3 filteredrows 的联动计算)
    • [三、`type` 类型全解:从"火箭"到"拖拉机"](#三、type 类型全解:从“火箭”到“拖拉机”)
      • [3.1 `system`(极罕见)](#3.1 system(极罕见))
      • [3.2 `const`(主键/唯一索引等值匹配)](#3.2 const(主键/唯一索引等值匹配))
      • [3.3 `eq_ref`(多表连接之王)](#3.3 eq_ref(多表连接之王))
      • [3.4 `ref` / `ref_or_null`](#3.4 ref / ref_or_null)
      • [3.5 `unique_subquery` / `index_subquery`](#3.5 unique_subquery / index_subquery)
      • [3.6 `range`(范围查询底线)](#3.6 range(范围查询底线))
      • [3.7 `index`(全索引扫描)vs `ALL`(全表扫描)](#3.7 index(全索引扫描)vs ALL(全表扫描))
    • [四、`Extra` 列深潜:那些决定生死的关键词](#四、Extra 列深潜:那些决定生死的关键词)
      • [4.1 `Using index`(索引覆盖,黄金标准)](#4.1 Using index(索引覆盖,黄金标准))
      • [4.2 `Using where`(回表后过滤)](#4.2 Using where(回表后过滤))
      • [4.3 `Using filesort`(外部排序,需优化)](#4.3 Using filesort(外部排序,需优化))
      • [4.4 `Using temporary`(临时表,需优化)](#4.4 Using temporary(临时表,需优化))
      • [4.5 `Using index condition`(索引下推 ICP)](#4.5 Using index condition(索引下推 ICP))
      • [4.6 `Using MRR`(多范围读取)](#4.6 Using MRR(多范围读取))
    • [五、核心机制深度剖析:覆盖索引 / 回表 / 索引合并](#五、核心机制深度剖析:覆盖索引 / 回表 / 索引合并)
      • [5.1 索引覆盖(Covering Index) vs 回表(Back to Table)](#5.1 索引覆盖(Covering Index) vs 回表(Back to Table))
      • [5.2 索引合并(Index Merge)三种算法详解](#5.2 索引合并(Index Merge)三种算法详解)
    • 六、优化SELECT的其他场景(MySQL优化器规则)
      • [6.1 WHERE子句优化(MySQL自动执行)](#6.1 WHERE子句优化(MySQL自动执行))
      • [6.2 范围优化(Range Access)的数学区间推导](#6.2 范围优化(Range Access)的数学区间推导)
      • [6.3 外连接优化(LEFT JOIN / RIGHT JOIN)](#6.3 外连接优化(LEFT JOIN / RIGHT JOIN))
      • [6.4 `IS NULL` 优化](#6.4 IS NULL 优化)
      • [6.5 `ORDER BY` 优化](#6.5 ORDER BY 优化)
      • [6.6 `GROUP BY` 与 `DISTINCT` 优化](#6.6 GROUP BYDISTINCT 优化)
      • [6.7 函数调用优化(确定性 vs 非确定性)](#6.7 函数调用优化(确定性 vs 非确定性))
    • [七、💣 索引失效的 8 大经典场景](#七、💣 索引失效的 8 大经典场景)
    • 八、索引设计实战黄金法则
    • 九、综合调优实战案例
    • [十、💡 面试高频问题速答](#十、💡 面试高频问题速答)
    • [📝 总结](#📝 总结)

📌 前言:调优的四个维度

数据库性能优化是一个多层面的工作,绝不仅仅是加索引。在实际生产中,优化需从以下四个层次自上而下审视:

优化层次 具体内容 负责人
硬件层 机械硬盘换SSD、增大内存、万兆网卡 DBA/运维
架构层 读写分离、分库分表、引入Redis缓存 架构师
配置层 调整innodb_buffer_pool_size(内存命中率)、sort_buffer_size(排序效率) DBA
SQL与设计层 表结构设计(数据类型)、索引设计、SQL语句编写质量 开发人员(重点)

核心观点:对于开发人员,80%的性能瓶颈源于糟糕的SQL语句和缺失的索引设计。在InnoDB中,索引即数据组织方式,用好索引,事半功倍。


一、先看效果:索引的"降维打击"实验

1.1 构建百万级测试数据

为了方便演示,我们先构造一张包含100万条记录的表(包含主键id和普通索引class_id)。注意:运行以下存储过程耗时较长(约20-100分钟),建议在测试环境执行。

sql 复制代码
-- 1. 修改SQL结束符
DELIMITER //

-- 2. 创建存储过程
CREATE PROCEDURE p_init_index_data ()
BEGIN
    DECLARE id BIGINT DEFAULT 100000;
    DECLARE age TINYINT DEFAULT 18;
    DECLARE gender BIGINT DEFAULT 1;
    DECLARE class_id BIGINT DEFAULT 1;
    DECLARE count INT DEFAULT 0;

    DROP TABLE IF EXISTS index_demo;
    CREATE TABLE index_demo (
        id BIGINT AUTO_INCREMENT,
        sn VARCHAR(10) NOT NULL,
        name VARCHAR(20) NOT NULL,
        mail VARCHAR(20),
        age TINYINT(1),
        gender TINYINT(1),
        password VARCHAR(36) NOT NULL,
        class_id BIGINT NOT NULL,
        create_time DATETIME NOT NULL,
        update_time DATETIME NOT NULL,
        PRIMARY KEY (id),
        INDEX (class_id)
    );

    INSERT INTO index_demo VALUES (100000, '100000', 'testUser', '100000@qq.com', 18, 1, UUID(), 1, NOW(), NOW());

    WHILE count < 1000000 DO
        SET id := id + 1;
        IF count % 10 = 0 THEN SET age := age + 1; END IF;
        IF age > 50 THEN SET age := 16; END IF;
        IF count % 3 = 0 THEN SET gender := 0; ELSE SET gender := 1; END IF;
        SET class_id := class_id + 1;
        IF class_id > 10 THEN SET class_id := 1; END IF;
        INSERT INTO index_demo VALUES (id, id, CONCAT('user_', id), CONCAT(id, '@qq.com'), age, gender, UUID(), class_id, NOW(), NOW());
        SET count := count + 1;
    END WHILE;
END //

DELIMITER ;

-- 调用存储过程
CALL p_init_index_data();
-- 验证数据
SELECT COUNT(*) FROM index_demo; -- 输出:1000001

1.2 主键查询 vs 无索引列查询

  • 主键查询(聚簇索引)SELECT * FROM index_demo WHERE id = 1020000; 耗时 0.00 sec
  • 无索引列查询(全表扫描)SELECT * FROM index_demo WHERE sn = '1020000'; 耗时 0.59 sec

同样的数据,性能相差近60倍

1.3 压测工具 mysqlslap 放大差距

使用MySQL自带的mysqlslap模拟并发,结果触目惊心:

① 主键查询(100并发,10000次查询)

bash 复制代码
mysqlslap -uroot -p123456 --concurrency=100 --iterations=100 \
--create-schema="topic01" --engine="innodb" --number-of-queries=10000 \
--query "select id, sn, name, mail, age, gender, class_id from topic01.index_demo where id = 1020000;"

结果Average number of seconds to run all queries: 0.203 seconds

② 无索引列查询(100并发,仅100次查询)

bash 复制代码
mysqlslap -uroot -p123456 --concurrency=3 --iterations=1 \
--create-schema="topic01" --engine="innodb" --number-of-queries=10 \
--query "select id, sn, name, mail, age, gender, class_id from topic01.index_demo where sn = '1020000';"

结果Average number of seconds to run all queries: 1001.484 seconds(约16分钟!)

结论:无索引时,并发稍大即导致数据库连接池耗尽。


二、调优核心利器:EXPLAIN 执行计划

在SQL前加EXPLAIN关键字,即可查看MySQL优化器生成的执行计划。

sql 复制代码
EXPLAIN SELECT id, sn, name FROM index_demo WHERE id = 1020000\G

2.1 执行计划完整字段列表

列名 核心解读 重点关注
id SELECT标识符,id越大越先执行,id相同则从上至下。 子查询/联合查询时看执行顺序
select_type 查询类型:SIMPLE(简单)、PRIMARY(外层)、SUBQUERY(子查询)、UNION/UNION RESULT。注意:INSERT/UPDATE/DELETE也会显示对应类型。 出现SUBQUERY时需留意能否优化
table 正在访问的表名。<unionM,N> 表示合并查询的临时表。 -
partitions 使用了哪个分区(非分区表为NULL)。 -
type 连接类型(性能排序) 调优核心指标
possible_keys 可能选用的索引(理论)。 -
key 实际选用的索引(实践) 是否为NULL
key_len 使用的索引字节长度。 推算使用了复合索引的多少列
ref 与索引比较的对象(常量const 或 某表的某列)。 -
rows 预估扫描行数(InnoDB是估值)。 越小越好
filtered 存储引擎返回后,Server层过滤后剩余的比例。rows * filtered ≈ 实际行数。 越高越好(100%最佳)
Extra 额外的执行策略信息 是否回表、是否排序

2.2 key_len 精确计算法(高频面试计算题)

key_len 显示的字节数,可倒推出SQL实际用到了复合索引的哪几列。

公式

key_len = 列定义长度 + (是否允许NULL ? 1 : 0) + (是否为变长类型VARCHAR ? 2 : 0)

举例 :复合索引 (name VARCHAR(20) NOT NULL, age TINYINT NULL),字符集utf8mb4

  • name 列:20 * 4 + 0 (NOT NULL) + 2 (VARCHAR) = 82 字节。
  • age 列:1 (TINYINT) + 1 (允许NULL) + 0 = 2 字节。
  • 如果执行计划 key_len = 82,说明只用了name
  • 如果 key_len = 84,说明 nameage都用上了

2.3 filteredrows 的联动计算

如果 rows 显示 1000filtered 显示 20.00,则最终返回给客户端的行数约为 1000 * 20% = 200 行。filtered 值越高,说明索引过滤性越好,回表浪费越少。


三、type 类型全解:从"火箭"到"拖拉机"

type 性能从高到低完整排序:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

3.1 system(极罕见)

  • 含义 :表只有一行数据(仅MyISAM引擎支持显示system,InnoDB即使只有一行也显示为ALLconst)。
sql 复制代码
CREATE TABLE test_system_myisam (id INT PRIMARY KEY, name VARCHAR(255)) ENGINE=MyISAM;
INSERT INTO test_system_myisam VALUES (1, 'name');
EXPLAIN SELECT * FROM test_system_myisam; -- type: system

3.2 const(主键/唯一索引等值匹配)

  • 含义:命中主键或唯一索引,且条件为常量等值,结果最多一行。
sql 复制代码
EXPLAIN SELECT * FROM index_demo WHERE id = 1020000; -- type: const

3.3 eq_ref(多表连接之王)

  • 含义 :多表JOIN中,被驱动表 的连接字段是主键唯一非空索引,且为等值匹配。
sql 复制代码
-- 假设 account 表的 student_id 是唯一索引
EXPLAIN SELECT * FROM student s JOIN account a ON s.id = a.student_id;
-- 对 account 表的扫描 type 为 eq_ref

3.4 ref / ref_or_null

  • ref:普通索引(非唯一)等值匹配,返回多条。
  • ref_or_null :相比ref,额外包含对IS NULL的检索。前提是列必须允许为NULL
sql 复制代码
ALTER TABLE index_demo MODIFY name VARCHAR(20) NULL;
EXPLAIN SELECT * FROM index_demo WHERE name = 'user' OR name IS NULL; -- type: ref_or_null

3.5 unique_subquery / index_subquery

针对 IN 子查询的特殊优化,面试时常被遗漏。

  • unique_subqueryIN 子查询返回的是主键/唯一键 ,用eq_ref方式替换子查询。
  • index_subqueryIN 子查询返回的是普通索引列 ,用ref方式替换子查询。

3.6 range(范围查询底线)

  • 含义 :使用 ><BETWEENIN()LIKE 'abc%'进行索引范围扫描。
sql 复制代码
EXPLAIN SELECT * FROM index_demo WHERE id BETWEEN 110000 AND 200000; -- type: range

生产环境要求 :绝大多数查询必须达到range及以上级别。

3.7 index(全索引扫描)vs ALL(全表扫描)

  • index:扫描了整个索引树(通常是因为查询列都在索引里,但没带WHERE条件)。
  • ALL :全表扫描(灾难),必须优化。

四、Extra 列深潜:那些决定生死的关键词

4.1 Using index(索引覆盖,黄金标准)

  • 含义 :查询所需的所有列都包含在某个索引树中,无需回表,直接返回索引数据。
sql 复制代码
-- 复合索引 (mail, age, class_id)
EXPLAIN SELECT mail, age, class_id FROM index_demo WHERE mail = '1020000@qq.com';
-- Extra: Using index

4.2 Using where(回表后过滤)

  • 含义:使用索引定位到主键后,需要回表读取完整行,再在Server层过滤。
sql 复制代码
EXPLAIN SELECT * FROM index_demo WHERE id < 102000; -- Extra: Using where

4.3 Using filesort(外部排序,需优化)

  • 含义ORDER BY无法利用索引,MySQL在内存(sort_buffer_size)或磁盘上进行额外排序。
  • 查看大小SHOW VARIABLES LIKE 'sort_buffer_size';(默认256KB)。可调大至16M。
sql 复制代码
EXPLAIN SELECT * FROM index_demo WHERE id < 1020000 ORDER BY age LIMIT 10;
-- Extra: Using filesort

4.4 Using temporary(临时表,需优化)

  • 含义GROUP BYDISTINCT未走索引,需要创建内部临时表。
sql 复制代码
EXPLAIN SELECT AVG(age) FROM index_demo GROUP BY gender; -- Extra: Using temporary

4.5 Using index condition(索引下推 ICP)

  • 含义 :MySQL 5.6+引入,在存储引擎层利用复合索引中未用于范围查找的列提前过滤,大幅减少回表次数。
  • 大白话:以前是"引擎查索引→回表→Server过滤",现在是"引擎查索引的同时,直接在索引上过滤→回表次数骤减"。

4.6 Using MRR(多范围读取)

  • 含义:将回表时的随机I/O转换为顺序I/O,提升磁盘效率(常与ICP配合出现)。

五、核心机制深度剖析:覆盖索引 / 回表 / 索引合并

5.1 索引覆盖(Covering Index) vs 回表(Back to Table)

概念 解释 性能影响 如何实现
索引覆盖 SELECT的列全部包含在索引中,数据直接从索引返回 极高(无需回表,减少随机I/O) 创建复合索引包含所有查询列
回表查询 根据索引查到主键,再根据主键到聚簇索引取整行 较差(大量随机I/O) 避免SELECT *,尽量只查索引列

5.2 索引合并(Index Merge)三种算法详解

索引合并是通过对一个表同时使用多个索引进行条件扫描,并将满足条件的多个主键集合取交集或并集后再进行回表。

算法 Extra显示 适用场景 原理
交集算法 Using intersect(...) AND条件连接多个不同索引 多个索引查出主键集合,取交集
并集算法 Using union(...) OR条件连接多个不同索引(等值查询) 多个索引查出主键集合,取并集
排序并集算法 Using sort_union(...) OR条件连接多个不同索引(范围查询 先分别查出主键,排序后再去重合并

建议 :虽然索引合并能救急,但复合索引通常比索引合并更高效


六、优化SELECT的其他场景(MySQL优化器规则)

6.1 WHERE子句优化(MySQL自动执行)

MySQL优化器在准备阶段会做以下等价变换(了解即可):

  1. 去除无效括号((a AND b) AND c) OR ((a AND b) AND (c AND d))(a AND b AND c) OR (a AND b AND c AND d)
  2. 常量合并(a<b AND b=c) AND a=5b>5 AND b=c AND a=5
  3. 常量条件去除(b>=5 AND b=5) OR (b=6 AND 5=5)b=5 OR b=6
  4. 无效值剔除TINYINTc < 256 直接优化为 1(永真)。
  5. 常量表优先读取 :主键/唯一键等值匹配的表(const表),在表连接中优先读取。

6.2 范围优化(Range Access)的数学区间推导

对于复合索引 (key_part1, key_part2, key_part3)

  • 当使用 =<=>IS NULL 时,精确锁定区间。
  • 当遇到第一个 ><>=<=BETWEEN 时,该列之后的所有列无法再用于缩小范围区间 ,但索引下推(ICP)仍可辅助过滤

示例key_part1 = 'foo' AND key_part2 >= 10 AND key_part3 > 10

  • 推导区间:('foo', 10, -inf) < (key_part1, key_part2, key_part3) < ('foo', +inf, +inf)
  • key_part3 仅能用于ICP过滤,不能缩小范围边界。

6.3 外连接优化(LEFT JOIN / RIGHT JOIN)

  • MySQL 不支持FULL OUTER JOINRIGHT JOIN 会被自动转换为 LEFT JOIN
  • 核心优化点 :如果 WHERE 条件中强过滤了右表(可空侧)的 NOT NULL 字段(如 WHERE score IS NOT NULLWHERE score > 80),则 外连接会被优化器自动降级为内连接(INNER JOIN),大幅提升优化空间。

6.4 IS NULL 优化

  • 如果列允许NULLIS NULL 走索引(typerangeref_or_null)。
  • 如果列设置了 NOT NULL,写 WHERE column IS NULL,执行计划会显示 Impossible WHERE(直接跳过查表)。

6.5 ORDER BY 优化

可以使用索引排序的情况

  1. ORDER BY 字段顺序与复合索引最左前缀完全一致
  2. 升降序(ASC/DESC)与索引方向一致(InnoDB支持反向扫描,但有额外开销)。
  3. WHERE 条件中引用的常量列,可以作为索引前缀的一部分。

无法使用索引排序的情况 (出现Using filesort):

  • 对不同的索引列排序。
  • 排序字段不在索引最左前缀。
  • 排序字段有表达式或函数。

6.6 GROUP BYDISTINCT 优化

GROUP BY 本质上会先排序或使用临时表。如果分组字段匹配索引最左前缀,则可直接利用索引顺序分组,避免Using temporary

特例MIN() / MAX() 如果作用在索引的最后一列,且前面列是常量,性能极高。

sql 复制代码
SELECT MAX(key_part2) FROM tbl WHERE key_part1 = 1; -- 走索引

6.7 函数调用优化(确定性 vs 非确定性)

  • 确定性函数 (如 POW(1,2)):结果固定,可使用索引。
  • 非确定性函数 (如 RAND()UUID()):每次结果不同,会导致索引失效

变通方案:将非确定性函数的结果先存入变量,再用于查询。

sql 复制代码
-- 错误(不走索引)
SELECT * FROM t WHERE id = FLOOR(1 + RAND() * 49);
-- 正确(走索引)
SET @keyval = FLOOR(1 + RAND() * 49);
SELECT * FROM t WHERE id = @keyval;

七、💣 索引失效的 8 大经典场景

失效场景 错误SQL示例 底层原因
1. 违反最左匹配 WHERE age = 20(索引是(name, age) B+树索引先按name排序,跳过name无法定位
2. 隐式类型转换 WHERE sn = 1020000snVARCHAR 触发隐式函数,索引"失效"
3. 索引列参与运算 WHERE id + 1 = 1000020 索引列值被修改,无法直接查找
4. 索引列使用函数 WHERE LENGTH(name) = 11 函数改变了原始值,索引无法匹配
5. LIKE 以 % 开头 WHERE name LIKE '%user%' B+树无法从中间匹配
6. 使用 <> 或 NOT IN WHERE name <> 'user' 结果集过大,优化器放弃索引
7. OR 连接不全覆盖索引(致命陷阱) WHERE id = 1 OR age = 20age无索引) 即使id有主键索引,OR两边必须都有索引,否则优化器大概率放弃索引走全表扫描
8. MySQL认为全表扫描更快 表中数据极少,或过滤条件区分度极低(如性别) 优化器基于统计信息计算代价,认为扫表更快

八、索引设计实战黄金法则

  1. 每张表必须有主键 ,推荐 BIGINT AUTO_INCREMENT(自增主键保证B+树顺序插入,避免页分裂)。严禁使用UUID做聚簇索引
  2. 为高频操作列建立索引WHEREJOINORDER BYGROUP BYDISTINCT 的列。
  3. 复合索引优先于多个单列索引(a,b,c) 相当于拥有了 (a)(a,b)(a,b,c) 三个索引(利用最左匹配)。
  4. 优先设计覆盖索引:避免回表,提升效率。
  5. 避免在高重复列上建索引:如性别,扫描二级索引再回表代价高于全表扫描。
  6. 控制索引总数:每张表建议不超过5-6个,维护索引有成本。
  7. 可以使用 USE INDEX / FORCE INDEX 强制指定索引。
  8. 定期清理未使用或重复索引。
  9. 创建索引前确认无未提交的大事务,防止锁表。
  10. SELECT COUNT(*) vs SELECT COUNT(1) 的终极真相
    • InnoDB :两者完全等价 ,无性能差异。底层会遍历最小的可用二级索引(若无则扫主键)。
    • MyISAM :无WHERE时直接返回精确行数(不扫表)。
    • 推荐写法 :统一使用 COUNT(*)

九、综合调优实战案例

原始慢SQL

sql 复制代码
SELECT * FROM index_demo WHERE mail = '1020000@qq.com' ORDER BY age LIMIT 10;
  • 假设 mail 有普通索引,age 无索引。
  • 执行计划type: refExtra: Using filesort

优化第一步:建立复合覆盖索引

sql 复制代码
CREATE INDEX idx_mail_age ON index_demo(mail, age);
  • 优化后执行计划type: refExtra: Using index(索引覆盖,且age利用索引有序,不再出现filesort)。

优化第二步(如果业务允许):避免SELECT *

sql 复制代码
SELECT mail, age FROM index_demo WHERE mail = '1020000@qq.com' ORDER BY age LIMIT 10;
  • 此时连回表都省了,直接走覆盖索引,达到极致性能。

十、💡 面试高频问题速答

  1. Q:什么是索引下推(ICP)?

    A :MySQL 5.6引入,在存储引擎层利用复合索引中未用于范围查找的列提前过滤,减少回表次数。Extra显示Using index condition

  2. Q:为什么LIKE '%xxx' 会导致索引失效?

    A:B+树索引按从左到右的顺序组织数据,无法跳过前缀直接定位到中间部分。

  3. Q:复合索引 (a,b,c),查询条件 WHERE a=1 AND c=3 会走索引吗?

    A :会走索引,但只会用到列 a(因为跳过了b,违反最左匹配,c无法用于缩小范围,但可能用于ICP过滤)。

  4. Q:SELECT * 一定不好吗?

    A :是的。SELECT * 几乎无法利用覆盖索引,必然导致回表,且传输冗余数据增加网络IO。

  5. Q:索引合并(Index Merge)是好事还是坏事?

    A :是优化器的补救措施。能用复合索引解决的,尽量不要依赖索引合并,因为多个索引扫描再合并的开销通常大于单次复合索引扫描。


📝 总结

  • 索引是查询的生命线,但需要科学设计,绝不是越多越好。
  • Explain 是调优的"火眼金睛" ,务必对 typekeyExtrakey_len 敏感。
  • 覆盖索引 是性能之王,回表是万恶之源。
  • 最左匹配、隐式转换、函数运算、OR乱用 是索引失效的四大天王,写SQL时务必警惕。

如果觉得有用,请点赞收藏,让更多小伙伴避开索引失效的深坑!有疑问欢迎评论区留言交流。👇

相关推荐
xyj29175964111 小时前
在Trae中配置数据库MCP
数据库·ai·mcp
廋到被风吹走1 小时前
【AI】【Claude】从 Prompt 到 Agent 的完整进阶地图
数据库·人工智能·prompt
数智化管理手记1 小时前
智能财务能替代人工核算吗?智能财务核心功能包含哪些?
大数据·网络·数据库·数据挖掘·精益工程
金智维科技官方1 小时前
DeepSeek接入企业系统:流程自动化新玩法
大数据·数据库·人工智能
小小龙学IT2 小时前
Tigris:下一代无服务器数据库
数据库·云原生·serverless
凤山老林2 小时前
ORM 框架性能调优:Spring Boot 下 N+1 查询根因治理、动态 SQL 优化与 Fetch 策略实战
数据库·spring boot·sql
laowangpython2 小时前
昆仑通态 Mcgs Pro软件安装步骤(附安装包)Mcgs Pro 3.3.6 下载安装教程(保姆级)
java·服务器·数据库·其他
是梦终空2 小时前
计算机毕业设计279—基于SpringBoot+Vue3校园商户意见反馈系统(源代码+数据库+17000字论文+ppt)
数据库·spring boot·vue·毕业设计·课程设计·毕业论文·源代码
TDengine (老段)3 小时前
TDengine 索引使用指南 — 何时建、怎么建、怎么用
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据