MySQL Join 的原理与优化实践

文章目录

    • 引言
    • 一、基础准备:创建环境与示例数据
      • 1. 初始化示例表
      • 2. 示例 Join 查询
      • 3. EXPLAIN 输出分析
    • 二、MySQL Join 的核心算法与执行机制
      • 1. 三种 Join 算法的实现与原理
        • 1.1 Index Nested-Loop Join(INLJ)
        • 1.2 Simple Nested-Loop Join(SNLJ)
        • 1.3 Block Nested-Loop Join(BNLJ)
        • 对比总结
      • 2. Join Buffer 的优化实践
        • 2.1 Join Buffer 的执行原理
        • 2.2 关键配置:Join Buffer 的大小
        • 2.3 Join Buffer 的性能分析
        • 2.4 Join Buffer 示例
      • 3. Batched Key Access(BKA)优化
        • 3.1 BKA 的基本原理
        • 3.2 与传统 Block Nested-Loop Join 的对比
        • 3.3 示例:开启 BKA
      • 4. Multi-Range Read(MRR)优化
    • 三、SQL Join 与非 Join 的选择
      • 1. Join 的代价分析
      • 2. 实际案例:决定是否使用 Join
        • 案例 1:只需一张表的汇总查询
        • 案例 2:多表关联查询
        • 案例总结
    • 四、MySQL Join 查询优化策略
      • 1. 索引设计与调整
        • 1.1 Join 列的索引设计
        • 1.2 索引优化案例
      • 2. 小表驱动大表
        • 2.1 驱动表的选择
        • 2.2 使用 STRAIGHT_JOIN 强制驱动表顺序
      • 3. 提前过滤无用数据
      • 4. 合理调整 Join Buffer
      • 5. BKA 与 MRR 技术
        • 5.1 Batched Key Access(BKA)
        • 5.2 Multi-Range Read(MRR)
    • 五、总结与实践指南
      • 1. MySQL Join 优化的核心思路
      • 2. 面向实践的优化流程


引言

Join 是数据库中最为重要且复杂的操作之一。在数据量较大的场景下,Join 的效率常常决定了整个查询的性能。本文旨在通过深入剖析 MySQL Join 的实现与优化,帮助读者理解其工作原理与实际应用中的性能优化策略。


一、基础准备:创建环境与示例数据

1. 初始化示例表

以下是构建的示例数据库表及其关系:

表名字段说明
usersid, name用户表,主键为 id
ordersid, user_id, product_id, order_date订单表,与 users 是 1 对多关系。
productsid, name, price产品表,与 orders 是多对 1 关系。

表结构及数据:

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

CREATE TABLE orders (
    id INT PRIMARY KEY,
    user_id INT,
    product_id INT,
    order_date DATE
);

CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    price DECIMAL(10, 2)
);

INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob');
INSERT INTO products VALUES (1, 'Laptop', 1000.00), (2, 'Phone', 500.00);
INSERT INTO orders VALUES (1, 1, 1, '2024-01-01'), (2, 2, 2, '2024-01-02');

2. 示例 Join 查询

以下是一个简单的三表 Join 查询:

SELECT u.name 用户名, p.name 产品名, o.order_date 订单日期
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN products p ON o.product_id = p.id;

查询结果:

用户名产品名订单日期
AliceLaptop2024-01-01
BobPhone2024-01-02

3. EXPLAIN 输出分析

通过 EXPLAIN 查看查询的执行计划:

1


二、MySQL Join 的核心算法与执行机制

1. 三种 Join 算法的实现与原理

在 MySQL 中,Join 的实现依赖三种核心算法。以下分别介绍这些算法的原理、适用场景,以及在实际应用中的优缺点。


1.1 Index Nested-Loop Join(INLJ)

算法原理:

  • 外层表逐行读取记录;
  • 对于每一行记录,使用内层表的索引快速查找匹配行。

适用场景:

  • 内层表的 Join 列已建立索引。
  • 外层表较小,内层表可以快速查找。

性能分析:

  • 扫描行数:
    • 外层表扫描行数:O(n)。
    • 内层表扫描行数:每行只需查找一次索引,时间复杂度为O(log m),扫描行数为1行。
  • 总时间复杂度:O(n log m)
  • 总扫描行数:O(2n)
1.2 Simple Nested-Loop Join(SNLJ)

算法原理:

  • 外层表逐行扫描;
  • 对于每一行记录,内层表全表扫描以寻找匹配行。

适用场景:

  • 内层表未建立索引。
  • 数据量较小时可接受。

性能分析:

  • 扫描行数:
    • 外层表扫描行数:O(n)。
    • 内层表扫描行数:每次全表扫描,复杂度为 O(m)。
  • 总时间复杂度:O(nm)
  • 总扫描行数:O(nm)
1.3 Block Nested-Loop Join(BNLJ)

算法原理:

  • 外层表数据加载到 Join Buffer。
  • 内层表逐行扫描,并与 Join Buffer 中的数据批量匹配。

适用场景:

  • 两张表均无索引。
  • 数据量较大,单次匹配耗时高。

性能分析:

  • 扫描行数:
    • 外层表一次性加载到 Join Buffer,减少多次扫描。
    • 总复杂度:取决于 Join Buffer 大小。

在Join Buffer够大的情况下,扫描行数跟时间复杂度其实跟SNL一样,只不过BNL是内存操作。

对比总结
算法适用场景优点缺点
Index Nested-Loop Join内层表有索引查询高效,减少内层扫描行数依赖索引,外层表仍需扫描所有行
Simple Nested-Loop Join无索引,小数据量简单实现,适合小型数据集内层表全表扫描,效率较低
Block Nested-Loop Join无索引,大数据量缓冲区减少扫描次数依赖内存大小,耗内存

2. Join Buffer 的优化实践

在没有索引支持的情况下,MySQL 使用 Join Buffer 来提升 Join 查询的性能,尤其是涉及大表的 Join 时,Join Buffer 的配置和使用至关重要。

2.1 Join Buffer 的执行原理

Join Buffer 的作用:

  • 临时缓冲区,用于存储外层表的数据,减少内层表的重复扫描次数。
  • 适用于无索引或不适合索引的场景,特别是需要 Block Nested-Loop Join 的情况。

执行步骤:

  1. 从外层表中加载一批数据到 Join Buffer 中。
  2. 内层表逐行扫描,并与 Join Buffer 中的数据逐一匹配。
  3. 若匹配成功,将结果返回;若缓冲区未完全匹配完内层表(Join Buffer 太小,数据太多),清空后继续加载下一批外层表数据。
2.2 关键配置:Join Buffer 的大小

系统变量 join_buffer_size

  • 定义 Join Buffer 的大小(默认值通常为 256KB)。
  • 配置得当时,可以显著减少内层表的扫描次数。
  • 调整示例:
SET join_buffer_size = 8M;

调整前后对比:
假设有以下两张表:

  • 外层表 users 有 1,000 行。
  • 内层表 orders 有 10,000 行。

join_buffer_size 分别设置为 1MB 和 4MB 时的性能表现如下:

join_buffer_size单次缓冲容纳的行数(假设每行大小为 1KB)缓冲批次数内层表扫描次数总扫描行数
1MB1,000110,000(1,000 + 10,000 = 11,000)
4MB4,000110,000(4,000 + 10,000 = 14,000)
2.3 Join Buffer 的性能分析

当 Join Buffer 足够大时:

  • 每次加载更多数据,减少外层表的加载频率。
  • 大幅降低内层表扫描的重复次数。

但是:

  • 若内存不足,可能会导致 MySQL 服务不稳定甚至崩溃。
  • Join Buffer 过大会浪费内存资源,且收益逐渐递减。
2.4 Join Buffer 示例

使用示例 SQL 分析 Join Buffer 的表现:

示例 SQL:

EXPLAIN SELECT u.name, o.id
FROM users u
JOIN orders o ON u.id = o.user_id;

执行计划(无索引):

idselect_typetabletyperowsExtra
1SIMPLEusersALL1000Using temporary
1SIMPLEordersALL10000Using join buffer (Block Nested Loop)

分析:

  • typeALL 表示全表扫描。
  • Extra 中的 Using join buffer 表明 MySQL 使用了 Join Buffer 来优化无索引的 Join 操作。

优化前后执行时间对比:

-- 默认 Join Buffer 大小:
SET join_buffer_size = 256K;

-- 调整后的 Join Buffer 大小:
SET join_buffer_size = 4M;

执行结果(在大表测试环境中):

  • 默认 join_buffer_size 时耗时:3.5秒
  • 调整为 4M 后耗时:1.2秒

3. Batched Key Access(BKA)优化

3.1 BKA 的基本原理

BKA(Batched Key Access) 是对传统 Nested-Loop Join 的改进,核心在于:

  • 使用批量索引访问,而非逐条访问索引,提高 I/O 效率。
  • 结合 Join Buffer,减少内存与磁盘之间的数据交换。

BKA 的工作流程:

  1. 批量从外层表加载数据到 Join Buffer。
  2. 根据 Join 条件,将 Join Buffer 中的记录转换为批量索引查找请求。
  3. 内层表按索引批量返回结果。

3.2 与传统 Block Nested-Loop Join 的对比
特性Block Nested-Loop Join(BNLJ)Batched Key Access(BKA)
数据加载方式批量加载外层表数据批量加载外层表数据
索引利用率不依赖索引必须依赖索引
数据访问效率随机访问批量顺序访问
扫描行数较多更少

BKA 的优势:

  • 避免频繁的随机 I/O。
  • 尤其适合内层表索引分布不均或查询条件复杂的情况。

3.3 示例:开启 BKA

默认情况下,MySQL 在特定条件下会自动启用 BKA。可通过以下配置确保 BKA 生效:

SET optimizer_switch = 'batched_key_access=on';

对比示例:
假设外层表 users 有 10,000 行,内层表 orders 有 50,000 行,user_id 上有索引。

  • 使用 BNLJ 时:

    • 外层表批量加载 1,000 行;
    • 每次对内层表随机访问 1,000 次。
  • 使用 BKA 时:

    • 外层表批量加载 1,000 行;
    • 内层表按索引顺序批量访问,减少随机 I/O 次数。

4. Multi-Range Read(MRR)优化

4.1 MRR 的基本原理

MRR(Multi-Range Read) 是另一种索引优化策略,主要用于减少索引范围查询中的随机访问。

原理:

  • 将索引的随机读取转换为顺序读取。
  • 按块读取数据,减少每次 I/O 的开销。

工作流程:

  1. 将索引范围查询的结果缓存在内存中。
  2. 对缓存的结果进行排序,按顺序访问实际数据行。

适用场景:

  • 索引范围查询,如 BETWEEN 或带排序的 ORDER BY
  • 随机访问代价较高的查询。

4.2 示例:开启 MRR

默认情况下,MySQL 会根据场景动态选择是否启用 MRR。可通过以下配置强制启用 MRR:

SET optimizer_switch = 'mrr=on';

MRR 示例对比:

EXPLAIN SELECT o.id
FROM orders o
WHERE o.product_id BETWEEN 10 AND 100;

性能分析:

  • 无 MRR 时,索引随机读取每行记录。
  • 有 MRR 时,索引范围查询的结果会先排序后读取,减少磁盘寻址时间。

三、SQL Join 与非 Join 的选择

在实际场景中,并非所有的多表关联查询都需要通过 Join 实现。在某些情况下,子查询、临时表甚至数据冗余存储可能是更高效的选择。因此,理解 Join 的代价与适用性,并结合具体场景选择合适的实现方式,至关重要。


1. Join 的代价分析

Join 的性能影响因素:

因素说明
表的数据量和分布数据量大、分布不均会导致更多扫描行数或增加 Join Buffer 压力。
索引设计是否合理Join 列上缺乏索引会触发全表扫描,导致性能显著下降。
过滤条件的选择性如果过滤条件的选择性较高(返回行数较少),则 Join 的代价显著降低。
Join 类型不同的 Join 类型(INNER, LEFT, RIGHT, FULL)对外层表和内层表的依赖程度不同,可能影响扫描行数。
查询复杂度复杂查询(如嵌套多层 Join)需要更多的资源和优化策略。

2. 实际案例:决定是否使用 Join

通过两个实际案例分析,在不同场景下选择 Join 或非 Join 的利弊。

案例 1:只需一张表的汇总查询

场景描述:
统计每个用户的订单总金额,不需要关联 products 表。

Join 方案:

SELECT u.name, SUM(p.price) AS total_amount
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN products p ON o.product_id = p.id
GROUP BY u.name;

非 Join 方案:

SELECT o.user_id, SUM(p.price) AS total_amount
FROM orders o
JOIN products p ON o.product_id = p.id
GROUP BY o.user_id;

优化分析:

  • 若最终只需用户 ID 和总金额,则非 Join 方案更高效,减少了对 users 表的访问。
  • 如果业务需求需要用户名称,则 Join 必不可少。
案例 2:多表关联查询

场景描述:
查询 2024 年 1 月的订单详情,包括用户名称和产品名称。

Join 方案:

SELECT u.name, p.name, o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN products p ON o.product_id = p.id
WHERE o.order_date >= '2024-01-01' AND o.order_date < '2024-02-01';

子查询方案:

WITH filtered_orders AS (
    SELECT user_id, product_id, order_date
    FROM orders
    WHERE order_date >= '2024-01-01' AND order_date < '2024-02-01'
)
SELECT u.name, p.name, o.order_date
FROM filtered_orders o
JOIN users u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id;

优化分析:

  • 子查询方案提前过滤订单数据,减少了 orders 表的扫描行数,适合大数据量场景。
  • Join 方案更直观,适合中小型数据集。
案例总结
场景Join 是否必要推荐方案
汇总查询(无关联需求)不必要使用单表查询或子查询优化,避免多余 Join。
多表关联查询必要若数据量较大,优先使用子查询减少扫描行数;若数据量小,直接 Join 效率更高。

四、MySQL Join 查询优化策略

在实际工作中,MySQL Join 的优化策略需要结合业务场景和硬件环境动态调整。以下将详细讨论几种常用优化方法,涵盖索引设计、执行顺序调整、Join Buffer 调整,以及 BKA 和 MRR 技术的高效利用。


1. 索引设计与调整

索引是 Join 性能优化的核心之一。在 Join 查询中,MySQL 会优先使用索引快速匹配数据,因此确保 Join 列有合适的索引尤为关键。

1.1 Join 列的索引设计

原则:

  • 对 Join 条件中的列建立索引。
  • 优先考虑复合索引,特别是频繁用于多列匹配的情况。

示例:

-- 为 orders 表的 user_id 和 product_id 列创建复合索引:
ALTER TABLE orders ADD INDEX idx_user_product (user_id, product_id);

索引的作用:

  • 索引可以将 Join 操作从全表扫描(ALL)优化为索引查找(refeq_ref)。
  • 减少内层表扫描的行数,显著降低查询时间。
1.2 索引优化案例

驱动表选择原则:

usersorders 的 Join 查询中,users 是主键表,orders 是从表(外键表)。MySQL 优化器通常会选择行数较少且 Join 列有索引的表作为驱动表(外层表)。

但在此案例中:

  1. 如果 usersorders 的行数接近或 orders 的数据量更大,那么 users 表很可能被选为驱动表。
  2. 如果 orders 数据量较少且 Join 列有索引,则优化器可能选择 orders 表作为驱动表。

案例:
1. 数据准备:批量插入数据

为了更清晰地模拟 MySQL 的行为,我们通过以下存储过程插入测试数据:

DELIMITER //

CREATE PROCEDURE generate_test_data()
BEGIN
    -- 清理旧数据
    DELETE FROM orders;
    DELETE FROM users;

    -- 插入 users 表测试数据(主表:1000 行)
    DECLARE i INT DEFAULT 1;
    WHILE i <= 1000 DO
        INSERT INTO users (id, name) VALUES (i, CONCAT('User', i));
        SET i = i + 1;
    END WHILE;

    -- 插入 orders 表测试数据(从表:10000 行)
    SET i = 1;
    WHILE i <= 10000 DO
        INSERT INTO orders (id, user_id, product_id, order_date)
        VALUES (i, FLOOR(1 + RAND() * 1000), FLOOR(1 + RAND() * 100), CURDATE() - INTERVAL FLOOR(RAND() * 30) DAY);
        SET i = i + 1;
    END WHILE;
END //

DELIMITER ;

-- 执行存储过程生成数据
CALL generate_test_data();

2. 查询分析:驱动表选择

以下为优化前后的查询对比,分析驱动表的选择及索引的作用。

原始查询

EXPLAIN SELECT users.name, orders.order_date
FROM users
JOIN orders ON users.id = orders.user_id;

执行计划(优化前,未添加索引):
2

驱动表分析:

  • 驱动表(外层表): orders 被选择为驱动表,因为 users 的主键索引使其能够高效响应关联条件。
  • 原因: orders 数据量较大,扫描代价相对较高,但由于 users 的索引能快速匹配,因此优化器倾向于选择 orders 为外层表。

优化查询

orders.user_id 添加索引,增强 Join 列的性能:

ALTER TABLE orders ADD INDEX (user_id);

再次执行查询:

EXPLAIN SELECT users.name, orders.order_date
FROM users
JOIN orders ON users.id = orders.user_id;

执行计划(优化后,添加索引):

3

驱动表分析:

  • 驱动表(外层表): 此时优化器选择了 users 表作为驱动表,因为 orders.user_id 索引使得内层表扫描行数大幅减少。
  • 原因: 索引的引入使得扫描行数显著降低,优化器调整了驱动表选择策略。

3. 驱动表选择的对比总结

在不同场景下,MySQL 的优化器行为会发生变化:

场景外层表(驱动表)内层表扫描行数(总行数)选择理由
未加索引ordersusers10294 + 1 = 10295users 的主键索引效率高,优化器倾向选择大表 orders 为驱动表
加索引usersorders1000 + 10 = 1010orders.user_id 索引生效,显著降低了内层表扫描行数

为什么未加索引时,扫描的行数是10249而不是10000?
在没有为 orders.user_id 添加索引时,MySQL 对 orders 表的扫描是全表扫描 (ALL)。
在这种情况下,优化器对扫描行数的估算基于表统计信息,例如数据的分布和块读取情况。
如果表的统计信息不准确或者数据分布较为不均衡(如随机生成的 user_id 有部分重复值),扫描时可能会多读取额外的数据块。
所以MySQL 会为了缓存块或磁盘预读而额外扫描相邻数据行,可能导致扫描行数增加。

2. 小表驱动大表

2.1 驱动表的选择

原则:

  • 优先选择小表作为驱动表(即外层表)。
  • 外层表的每一行都会触发内层表的扫描,因此外层表越小,扫描次数越少。

示例:

-- 默认 Join 查询,MySQL 自动选择驱动表:
SELECT u.name, o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id;
2.2 使用 STRAIGHT_JOIN 强制驱动表顺序

在某些情况下,MySQL 的查询优化器可能会错误选择驱动表顺序。可以使用 STRAIGHT_JOIN 强制指定驱动表:

SELECT STRAIGHT_JOIN u.name, o.order_date
FROM orders o
JOIN users u ON u.id = o.user_id;

效果:

  • 强制 orders 为外层表,减少了扫描行数。

3. 提前过滤无用数据

原则:

  • 尽量在 Join 之前过滤掉无关数据,减少 Join 操作时的行数。
  • 过滤可以通过子查询、WHERE 条件提前完成。

示例优化:

-- 原始查询:过滤条件放在 Join 后
SELECT u.name, p.name, o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN products p ON o.product_id = p.id
WHERE o.order_date > '2024-01-01';

优化查询:将过滤提前:

SELECT u.name, p.name, o.order_date
FROM (SELECT * FROM orders WHERE order_date > '2024-01-01') o
JOIN users u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id;

优化效果:

  • 原始查询需要扫描 orders 表的所有数据。
  • 优化后,提前过滤无关订单数据,减少了外层表的数据量,降低了 Join 的行数和成本。

4. 合理调整 Join Buffer

在无索引或索引不可用的情况下,Join Buffer 是优化 Block Nested-Loop Join 的关键。其大小直接影响外层表加载的行数和内层表的扫描效率。

默认值:

  • 通常 MySQL 的默认 join_buffer_size 为 256KB。

调整方式:

SET join_buffer_size = 4M;

注意事项:

  • Join Buffer 大小不宜设置过大,以免占用过多内存导致系统不稳定。
  • 可根据业务测试结果动态调整大小。

5. BKA 与 MRR 技术

5.1 Batched Key Access(BKA)

原理:

  • 使用批量索引读取,而非逐条访问。
  • 减少了随机 I/O 次数,提高查询性能。

BKA 优化示例:

SET optimizer_switch = 'batched_key_access=on';

SELECT u.name, o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id;

效果对比:

  • 无 BKA:每次外层表记录需要随机查找内层表索引。
  • 有 BKA:批量加载外层表数据,内层表按索引顺序批量返回结果。
5.2 Multi-Range Read(MRR)

原理:

  • 将索引的随机读取转换为顺序读取,优化索引范围查询的效率。

适用场景:

  • 索引范围查询,如 BETWEEN 或带排序的 ORDER BY 查询。

MRR 示例:

SET optimizer_switch = 'mrr=on';

EXPLAIN SELECT o.id
FROM orders o
WHERE o.product_id BETWEEN 10 AND 100;

优化效果:

  • 无 MRR 时,索引随机读取每行记录,导致更多磁盘寻址操作。
  • 开启 MRR 后,索引范围查询结果先排序,减少磁盘 I/O。

五、总结与实践指南

通过本文的深入解析,可以总结出以下优化建议:

1. MySQL Join 优化的核心思路

  • 索引优先: 确保 Join 列有适当的索引,优先使用覆盖索引。
  • 合理选择驱动表: 优先选择小表作为驱动表,使用 STRAIGHT_JOIN 控制查询顺序。
  • 动态调整 Join Buffer: 根据数据量测试合理的 Join Buffer 大小。
  • 利用高级技术: 在适用场景中开启 BKA 和 MRR,优化随机 I/O。

2. 面向实践的优化流程

  1. 使用 EXPLAIN 分析查询计划,定位性能瓶颈。
  2. 针对 Join 列设计索引,尽量减少全表扫描。
  3. 在无索引场景下,调整 Join Buffer,避免频繁磁盘 I/O。
  4. 在大数据量查询中,提前过滤无关数据,减少行数。
  5. 结合具体场景,选择合适的算法与优化技术。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/921814.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于安卓模拟器或手机设置了BurpSuite代理和安装证书后仍然抓取不到APP数据包的解决办法

免责申明 本文仅是用于学习研究安卓系统设置代理后抓取不到App数据包实验,请勿用在非法途径上,若将其用于非法目的,所造成的一切后果由您自行承担,产生的一切风险和后果与笔者无关;本文开始前请认真详细学习《‌中华人民共和国网络安全法》【学法时习之丨网络安全在身边一…

飞凌嵌入式旗下教育品牌ElfBoard与西安科技大学共建「科教融合基地」

近日&#xff0c;飞凌嵌入式与西安科技大学共同举办了“科教融合基地”签约揭牌仪式。此次合作旨在深化嵌入式创新人才的培育&#xff0c;加速科技成果的转化应用&#xff0c;标志着双方共同开启了一段校企合作的新篇章。 出席本次签约揭牌仪式的有飞凌嵌入式梁总、高总等一行…

下载安装Android Studio

&#xff08;一&#xff09;Android Studio下载地址 https://developer.android.google.cn/studio 滑动到 点击下载文档 打开新网页 切换到english ![](https://i-blog.csdnimg.cn/direct/b7052b434f9d4418b9d56c66cdd59fae.png 等待一会&#xff0c;出现 点同意后&#xff0…

准备阶段 Profiler性能分析工具的使用(一)

Unity 性能分析器 (Unity Profiler) 性能分析器记录应用程序性能的多个方面并显示相关信息。使用此信息可以做出有关应用程序中可能需要优化的事项的明智决策&#xff0c;并确认所做的优化是否产生预期结果。 默认情况下&#xff0c;性能分析器记录并保留游戏的最后 300 帧&a…

01Web3.0行业

目录 一、什么是Web 3.0? 二、Web 1.0 vs Web 2.0 vs Web 3.0 三、为什么选择Web 3.0 四、从法律角度观察Web 3.0 1. Web 3.0前时代的数字身份 问题1&#xff1a;个人信息的过度收集 问题2&#xff1a;个人信息的泄露和滥用 2. Web 3.0的解决方案及其法律问题 问题一&…

archlinux安装waydroid

目录 参考资料 注意 第一步切换wayland 第二步安装binder核心模组 注意 开始安装 AUR安裝Waydroid 启动waydroid 设置网络&#xff08;正常的可以不看&#xff09; 注册谷歌设备 安装Arm转译器 重启即可 其他 参考资料 https://ivonblog.com/posts/archlinux-way…

互联网时代的隐私保护

在这个数字化时代&#xff0c;我们的生活与互联网密不可分。打开手机刷刷朋友圈&#xff0c;浏览一下购物网站&#xff0c;约个网约车&#xff0c;点个外卖&#xff0c;这些看似平常的行为都在默默产生着数据足迹。可就在这不经意间&#xff0c;我们的个人信息正在被收集、分析…

python之使用django框架开发web项目

本问将对django框架在python的web项目中的使用进行介绍,有不对之处,烦请指正。 首先使用创建一个django工程(本示例中使用pycharm2024+python3.12),名称和项目保存路径根据自己的需要自行修改,新手直接默认本机环境就好(关于conda将会另开一篇进行讲解。),最后点击cre…

基于YOLOv8深度学习的扰乱公共秩序打架异常行为检测系统研究与实现(PyQt5界面+数据集+训练代码)

随着智能监控技术和人工智能的发展&#xff0c;基于深度学习的行为检测技术在公共安全和防范领域中发挥着越来越重要的作用。传统的监控系统通常依赖于人工监控&#xff0c;这不仅耗费大量的人力和时间&#xff0c;且容易因为人的疲劳或疏忽而漏检关键的异常行为。而近年来&…

gocv调用opencv添加中文乱码的解决方案

前言 相信很多做视觉的同学在使用opencv给图片添加中文文字的时候会出现这样的乱码显示: 而实际上你期望的是“告警时间:2011-11-11 11:11:11 告警类型:脱岗检测告警 Area:XXXXX Camera:Camera001-001”这样的显示内容,那么这篇文章我将用很简单的方法来解决乱码问题,只需…

JavaScript中的this指向问题

JavaScript中的this指向问题 1.1 为什么需要this? 为什么需要this? 在常见的编程语言中&#xff0c;几乎都有this这个关键字&#xff08;Objective-C中使用的是self),但是在JavaScript中的this和常见的面向对象语言中的this不太一样 常见面向对象的编程语言中&#xff0c;比…

预测气动阻尼

TLDR&#xff1a;通过结合 ANSYS Mechanical 和 ANSYS CFX&#xff0c;可以通过模拟预测气动阻尼。此方法可用于涡轮叶片、飞机机翼或 MEMS 微镜&#xff01; MEMS 系统的频率响应。峰值的高度取决于阻尼……那么阻尼比是多少&#xff1f; 多年来&#xff0c;很多人问我“嘿&am…

在 CentOS 系统上直接安装 MongoDB 4.0.25

文章目录 步骤 1&#xff1a;配置 MongoDB 官方源步骤 2&#xff1a;安装 MongoDB步骤 3&#xff1a;启动 MongoDB 服务步骤 4&#xff1a;验证安装步骤 5&#xff1a;可选配置注意事项 以下是在 CentOS 系统上直接安装 MongoDB 4.0.25 的详细步骤&#xff1a; 步骤 1&#x…

.NET9 - 新功能体验(一)

被微软形容为“迄今为止最高效、最现代、最安全、最智能、性能最高的.NET版本”——.NET 9已经发布有一周了&#xff0c;今天想和大家一起体验一下新功能。 此次.NET 9在性能、安全性和功能等方面进行了大量改进&#xff0c;包含了数千项的修改&#xff0c;今天主要和大家一起体…

乐理的学习(调式)

大致了解乐理之后的总结 跟着西蒙哥也是把基础乐理差不多能有一个大致的总结框架了&#xff0c;主要还是为了弹钢琴&#xff0c;也是知道了很多的规则都是为了人们的感受服务的 对手指要了解 对于手指的弹音局限 各个手指的使用频率 不同年龄的不同的人对手指的使用存在差…

08 —— Webpack打包图片

【资源模块 | webpack 中文文档 | webpack中文文档 | webpack中文网】https://www.webpackjs.com/guides/asset-modules/?sid_for_share99125_3 Webpack打包图片以8KB为临界值判断 大于8KB的文件&#xff1a;发送一个单独的文件并导出URL地址 小于8KB的文件&#xff1a;导出一…

Python爬虫能处理动态加载的内容吗?

Python爬虫确实可以处理动态加载的内容。动态加载的内容通常是通过JavaScript在客户端执行&#xff0c;这意味着当网页首次加载时&#xff0c;服务器返回的HTML可能并不包含最终用户看到的内容。相反&#xff0c;JavaScript代码会在页面加载后从服务器请求额外的数据&#xff0…

SQL注入--DNSlog外带注入--理论

什么是DNSlog? DNS的作用是将域名解析为IP 而DNSlog就是存储在DNS服务器上的域名信息&#xff0c;它记录着用户对域名访问信息。可以理解为DNS服务器上的日志文件。 多级域名 比如blog.csdn.net&#xff0c;以点为分隔&#xff0c;从右向左依次是顶级域名、二级域名、三级域…

【Flask+Gunicorn+Nginx】部署目标检测模型API完整解决方案

【Ubuntu 22.04FlaskGunicornNginx】部署目标检测模型API完整解决方案 文章目录 1. 搭建深度学习环境1.1 下载Anaconda1.2 打包环境1.3 创建虚拟环境1.4 报错 2. 安装flask3. 安装gunicorn4. 安装Nginx4.1 安装前置依赖4.2 安装nginx4.3 常用命令 5. NginxGunicornFlask5.1 ng…

速度革命:esbuild如何改变前端构建游戏 (1)

什么是 esbuild&#xff1f; esbuild 是一款基于 Go 语言开发的 JavaScript 构建打包工具&#xff0c;以其卓越的性能著称。相比传统的构建工具&#xff08;如 Webpack&#xff09;&#xff0c;esbuild 在打包速度上有着显著的优势&#xff0c;能够将打包速度提升 10 到 100 倍…