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

MySQL 为什么一定要有一个主键

引言

在数据库设计中,主键(Primary Key)是一个至关重要的概念。MySQL 作为最广泛使用的关系型数据库之一,主键在 MySQL 表设计中扮演着关键角色。主键不仅决定了表中数据的唯一性和完整性,还对数据库性能、数据查询、数据完整性和存储引擎有着直接影响。

在这篇文章中,我们将深入探讨为什么 MySQL 中的每张表都应该有一个主键,主键的作用及其对性能的影响,并通过代码和图文示例详细讲解主键在数据库中的实际应用。我们将涵盖主键的概念、工作原理、与索引的关系、MySQL 存储引擎(如 InnoDB)对主键的依赖等多个方面,力求提供对主键设计的全面理解。


第一部分:主键的基础概念

1.1 什么是主键

主键(Primary Key)是关系数据库中的一个列或多列的组合,它的值能够唯一地标识表中的每一行记录。主键的特点是:

  1. 唯一性:主键的每个值都是唯一的,保证表中没有重复的记录。
  2. 非空:主键列不能为 NULL,必须有明确的值。
  3. 唯一标识:通过主键,可以快速地找到指定的行数据,起到唯一标识记录的作用。

在 MySQL 中,主键可以是单列(Single-column Primary Key)或多列的组合(Composite Primary Key)。

1.1.1 单列主键示例
CREATE TABLE users (user_id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL
);

在这个示例中,user_id 是表的主键,它的值是唯一的,并且通过 AUTO_INCREMENT 自动递增。

1.1.2 组合主键示例
CREATE TABLE orders (order_id INT NOT NULL,product_id INT NOT NULL,quantity INT NOT NULL,PRIMARY KEY (order_id, product_id)
);

在这个示例中,order_idproduct_id 的组合构成了主键,确保同一个订单中不能有相同的产品。

1.2 为什么主键重要

主键在数据库设计中扮演着极其重要的角色,原因包括以下几点:

  1. 唯一性约束:主键确保表中的记录是唯一的,防止出现重复数据。
  2. 快速查询:通过主键可以快速定位特定的记录,这使得数据库的查询效率大大提高。
  3. 外键约束:主键通常用于建立与其他表的外键关联,从而维持数据库中表与表之间的关系完整性。
  4. 存储引擎依赖:MySQL 中的 InnoDB 存储引擎需要主键来组织数据,因此主键在数据存储和检索方面至关重要。

第二部分:主键与 MySQL 存储引擎的关系

2.1 MySQL 存储引擎介绍

MySQL 支持多种存储引擎,其中最常用的是 InnoDBMyISAM。不同的存储引擎对主键的处理方式不同。InnoDB 是 MySQL 的默认存储引擎,它对主键有特别的依赖。

2.1.1 InnoDB 与 MyISAM 的区别
  • InnoDB

    • 支持事务和外键。
    • 使用 聚簇索引(Clustered Index)来存储数据,主键是聚簇索引的一部分。
    • 需要表中至少有一个主键,如果没有显式定义主键,InnoDB 会自动选择一个合适的列作为主键,或者创建一个隐藏的主键列。
  • MyISAM

    • 不支持事务和外键。
    • 使用 非聚簇索引(Non-Clustered Index)来存储数据,主键只是一个普通索引。

由于 InnoDB 的广泛使用,我们将重点探讨 InnoDB 对主键的依赖。

2.2 聚簇索引与主键的关系

InnoDB 使用聚簇索引存储数据。在聚簇索引中,表中的数据行实际上存储在主键的叶节点上。这意味着:

  1. 数据按照主键顺序存储:表中的行数据按主键值的顺序存储在磁盘上,主键值决定了数据的物理存储顺序。
  2. 主键作为索引的基础:其他非主键列的索引,实际上是指向主键的索引,而不是直接指向行数据。
2.2.1 聚簇索引的工作原理

每当你插入一行数据时,InnoDB 会根据主键的值将数据存储在合适的位置。如果表中没有定义主键,InnoDB 会为你自动生成一个隐式的主键。

2.2.2 聚簇索引的示意图
+--------------------+
|  Primary Key Index |
+--------------------+
| 1 -> Data Row 1    |
| 2 -> Data Row 2    |
| 3 -> Data Row 3    |
+--------------------+

如上图所示,主键值作为聚簇索引的叶节点,直接指向对应的行数据。

2.3 没有主键的影响

如果在 InnoDB 中没有定义主键,MySQL 会自动为表添加一个隐藏列作为主键,但这会带来性能问题:

  1. 性能下降:因为没有显式主键,InnoDB 无法有效地组织数据,导致查询和插入性能下降。
  2. 数据管理困难:如果没有主键,数据的唯一性和完整性无法保证,可能会导致数据重复或不一致。

第三部分:主键对性能的影响

3.1 主键的查询性能

主键查询是一种 O(log n) 的操作,因为主键是有序的,数据库可以使用二分查找算法在 B+ 树索引中快速定位数据。这使得主键查询比非主键列的查询速度更快。

3.1.1 查询主键的示例
SELECT * FROM users WHERE user_id = 1;

在这个查询中,MySQL 会使用主键索引在 user_id 列中快速找到对应的行。

3.1.2 复杂查询优化

主键的存在还可以帮助优化复杂查询。当涉及到多表联合查询或复杂的过滤条件时,数据库引擎会首先使用主键索引进行初步过滤,从而大幅减少需要扫描的数据量。

3.2 插入性能与主键

在插入数据时,主键的有序性也影响性能。由于 InnoDB 使用聚簇索引存储数据,新的记录必须插入到合适的位置,以保持主键索引的有序性。

  • 顺序插入:如果主键是自增的,插入新数据时,总是追加到表的末尾,这种情况性能最佳。
  • 随机插入:如果主键是随机值(如 UUID),新数据可能需要插入到表的中间,导致页面分裂和性能下降。
3.2.1 自增主键的插入示例
INSERT INTO users (username) VALUES ('Alice');

在这个示例中,user_id 是自增的,因此每次插入新数据时,记录都被追加到表的末尾,插入操作非常高效。

3.3 索引和主键的结合

在 MySQL 中,主键也是一种索引。主键索引的作用不仅仅是确保数据的唯一性,还可以极大地提高数据的检索速度。主键索引和其他普通索引不同,它是基于聚簇索引实现的。

3.3.1 创建主键索引的示例
CREATE TABLE products (product_id INT AUTO_INCREMENT PRIMARY KEY,product_name VARCHAR(100) NOT NULL,price DECIMAL(10, 2)
);

在这个示例中,product_id 被设置为主键,它不仅确保产品 ID 的唯一性,还在数据检索时提供了高效的索引查找。


第四部分:主键与数据完整性

4.1 数据唯一性约束

主键是数据库保证数据唯一性的核心机制。通过为表设置主键,数据库能够自动避免重复数据的插入。例如,如果尝试插入一条与现有记录主键相同的数据,数据库会抛出错误,从而确保数据的唯一性。

4

.1.1 唯一性约束的示例

INSERT INTO users (user_id, username) VALUES (1, 'Bob');
-- 如果 user_id=1 的记录已经存在,这条插入语句将会失败

在这个例子中,如果表中已经有一条 user_id=1 的记录,插入新记录时将会失败。

4.2 外键约束与主键的结合

主键在数据库的外键关系中也起到了关键作用。外键用于维护表与表之间的关系,通常指向另一个表的主键。当主表的主键被更新或删除时,外键约束可以确保引用表中的数据保持一致性。

4.2.1 外键约束示例
CREATE TABLE orders (order_id INT AUTO_INCREMENT PRIMARY KEY,user_id INT,product_id INT,FOREIGN KEY (user_id) REFERENCES users(user_id),FOREIGN KEY (product_id) REFERENCES products(product_id)
);

在这个例子中,orders 表中的 user_idproduct_id 分别指向 usersproducts 表的主键。这种主键-外键关系保证了订单表中的用户和产品必须在对应的用户和产品表中存在。

4.3 参照完整性与主键

参照完整性是指数据库中表与表之间的关系必须保持一致。例如,不能在子表中插入一个不存在的父表主键。在数据库设计中,主键是维护参照完整性的基础。

4.3.1 参照完整性示例
-- 尝试插入一个不存在的 user_id
INSERT INTO orders (user_id, product_id) VALUES (999, 1);
-- 此操作将失败,因为 user_id=999 不存在于 users 表中

通过外键和主键的结合,数据库可以确保数据的完整性,防止不一致的数据插入。


第五部分:主键的设计原则与最佳实践

5.1 单列主键 vs 组合主键

在数据库设计中,主键可以是单列,也可以是多列组合的。选择哪种主键取决于具体的业务需求。

  • 单列主键:通常使用自增整数作为主键,简单、高效。
  • 组合主键:用于多字段联合唯一约束的场景,例如订单表中,订单 ID 和产品 ID 的组合可以作为主键,防止同一个订单中重复添加相同的产品。
5.1.1 组合主键示例
CREATE TABLE order_items (order_id INT,product_id INT,quantity INT,PRIMARY KEY (order_id, product_id)
);

5.2 自增主键 vs UUID 主键

在选择主键类型时,自增主键和 UUID 是两种常见的选择。每种方式都有其优缺点。

  • 自增主键:简单、性能高,但在分布式系统中可能会产生重复 ID 或 ID 冲突。
  • UUID 主键:在分布式系统中非常有用,因为它们是全局唯一的,但它们的长度更长,查询性能可能不如自增主键。
5.2.1 UUID 主键示例
CREATE TABLE users (user_id CHAR(36) PRIMARY KEY,username VARCHAR(50) NOT NULL
);

在这个例子中,user_id 使用 UUID 作为主键,保证了全局唯一性。

5.3 避免使用业务字段作为主键

业务字段(如邮箱、用户名)虽然具有唯一性,但不建议用作主键。因为业务字段可能会发生变化,修改主键会导致大量索引更新,降低数据库性能。推荐使用与业务无关的字段作为主键,例如自增 ID 或 UUID。


第六部分:没有主键的潜在问题

6.1 数据重复问题

如果没有主键,数据库无法强制保证记录的唯一性,可能导致数据重复。例如,在用户表中,没有主键约束,可能会出现多个相同的用户记录。

6.1.1 数据重复示例
INSERT INTO users (username) VALUES ('Alice');
-- 由于没有主键,可能插入多条相同记录

6.2 数据管理的困难

没有主键,数据的管理和查询将变得复杂。例如,在更新或删除记录时,无法准确定位某一行数据,因为没有唯一标识符。

6.2.1 更新或删除记录的困难
UPDATE users SET username = 'Bob' WHERE username = 'Alice';
-- 如果表中有多条 'Alice' 记录,这条语句将更新所有记录

6.3 索引和查询性能的下降

如果表没有主键,InnoDB 会为表自动生成一个隐藏的主键,但这会导致索引效率低下,查询性能下降。


第七部分:主键的特殊情况与解决方案

7.1 自增主键的溢出问题

对于使用自增主键的表,主键值有可能达到其上限,导致插入失败。解决方法可以是将自增主键的类型改为更大范围的数据类型(如从 INT 改为 BIGINT)。

7.1.1 自增主键溢出示例
ALTER TABLE users MODIFY user_id BIGINT AUTO_INCREMENT;

7.2 UUID 主键的性能优化

由于 UUID 的长度较长,查询性能可能不如自增主键。为了解决这一问题,可以采用分片 UUID 或优化索引结构。


第八部分:MySQL 主键与分布式系统

8.1 分布式系统中的全局唯一标识符

在分布式系统中,需要保证每个主键在全局范围内唯一。自增主键在分布式场景下容易产生冲突,因此通常使用 UUID 或雪花算法(Snowflake)生成全局唯一的主键。

8.2 雪花算法生成唯一 ID

雪花算法(Snowflake)是 Twitter 开发的一个分布式 ID 生成算法,能够在分布式系统中生成唯一的主键 ID。

8.2.1 雪花算法示例
public class SnowflakeIdGenerator {private long workerId;private long datacenterId;private long sequence;public SnowflakeIdGenerator(long workerId, long datacenterId) {this.workerId = workerId;this.datacenterId = datacenterId;this.sequence = 0L;}public synchronized long nextId() {long timestamp = System.currentTimeMillis();return ((timestamp - epoch) << 22)| (datacenterId << 17)| (workerId << 12)| sequence++;}
}

第九部分:总结

通过本文的详细讲解,我们可以清楚地理解为什么 MySQL 表中必须有一个主键。主键不仅确保了数据的唯一性和完整性,还对数据库的性能、存储引擎、数据查询等各个方面有着深远的影响。在设计数据库时,合理选择和设计主键是保障系统高效、稳定运行的关键。

相关文章:

MySQL 为什么一定要有一个主键

引言 在数据库设计中&#xff0c;主键&#xff08;Primary Key&#xff09;是一个至关重要的概念。MySQL 作为最广泛使用的关系型数据库之一&#xff0c;主键在 MySQL 表设计中扮演着关键角色。主键不仅决定了表中数据的唯一性和完整性&#xff0c;还对数据库性能、数据查询、…...

Pycharm 本地搭建 stable-diffusion-webui

一、下载工程源码 Github官方连接 https://github.com/AUTOMATIC1111/stable-diffusion-webui 二、Pycharm打开工程 1、设置环境 文件-设置-项目-Python解析器-添加解释器-添加本地解释器 Conda环境-创造新环境-Python版本3.10 注意一定要选择Python3.10版本&#xff0c;否…...

python/爬虫技术/lxml工具介绍/XML和HTML解析

1.lxml介绍&#xff1a; lxml 是一个Python库&#xff0c;它提供了非常强大的XML和HTML解析功能。它基于libxml2和libxslt&#xff0c;是处理XML和HTML文档的首选库之一。 2.安装 首先&#xff0c;需要安装lxml库。可以通过pip来安装&#xff0c;在控制台内执行安装命令。 p…...

Kafka技术详解[5]: 集群启动

目录 集群启动 相关概念 代理&#xff1a;Broker 控制器&#xff1a;Controller 启动ZooKeeper 启动Kafka 初始化ZooKeeper 初始化服务 启动任务调度器 创建数据管理器 创建远程数据管理器 创建副本管理器 创建ZK元数据缓存 创建Broker通信对象 创建网络通信对象 注册Brok…...

记一次教学版内网渗透流程

信息收集 如果觉得文章写的不错可以共同交流 http://aertyxqdp1.target.yijinglab.com/dirsearch dirsearch -u "http://aertyxqdp1.target.yijinglab.com/"发现 http://aertyxqdp1.target.yijinglab.com/joomla/http://aertyxqdp1.target.yijinglab.com/phpMyA…...

[Python学习日记-31] Python 中的函数

[Python学习日记-31] Python 中的函数 简介 语法定义 函数的参数 简介 引子&#xff1a; 你是某公司的一个高级程序员&#xff0c;现在老板让你写一个监控程序&#xff0c;需要24小时全年无休的监控公司网站服务器的系统状况&#xff0c;当 CPU、Memory、Disk 等指标的使用…...

Kafak入门技术详解

抱歉&#xff0c;没有太多的时间进行详细校对 目录 一、Kafka简介 1.消息队列 1.1为什么需要消息队列 1.2消息队列 1.3消息队列的分类 1.4P2P和发布订阅MQ的比较 1.5消息系统的使用场景 1.6常见的消息系统 2.Kafka简介 2.1简介 2.2设计目标 2.3 kafka核心的概念 二…...

X-Spreadsheet:Web端Excel电子表格工具库

在数字化时代&#xff0c;数据管理与分析的重要性日益凸显。传统的电子表格软件如Microsoft Excel和Google Sheets在数据处理方面发挥着重要作用&#xff0c;但在Web端&#xff0c;一款名为X-Spreadsheet的工具库正以其独特的优势逐渐崭露头角。本文将详细介绍X-Spreadsheet&am…...

为什么很多APP取消网页版

厂商为了增加用户黏度把所有的内容都放在 APP 上&#xff0c;京东的网页也搜索不到东西了&#xff0c;就算看到东西要跳转过来还需要先登录一下。 对比亚马逊这类的其他的购物网站&#xff0c;基本上都是网页内容和 APP 的内容都是同步的&#xff0c;网页直接看也可以下单&…...

Kubernetes高级功能

资源配额 什么是资源配额 资源配额&#xff0c;通过 ResourceQuota 对象来定义&#xff0c;对每个命名空间的资源消耗总量提供限制。 它可以限制命名空间中某种类型的对象的总数目上限&#xff0c;也可以限制命名空间中的 Pod 可以使用的计算资源的总上限。 资源配额应用 创建的…...

(作业)第三期书生·浦语大模型实战营(十一卷王场)--书生入门岛通关第1关Linux 基础知识

关卡任务 闯关任务需要在关键步骤中截图&#xff1a; 任务描述 完成所需时间 闯关任务 完成SSH连接与端口映射并运行hello_world.py 10min 可选任务 1 将Linux基础命令在开发机上完成一遍 10min 可选任务 2 使用 VSCODE 远程连接开发机并创建一个conda环境 10min 可选任务 3 创…...

【python爬取网页信息并存储】

爬取网页信息并存储是一个常见的任务&#xff0c;通常涉及以下几个步骤&#xff1a; 发送HTTP请求&#xff1a;使用库如requests来发送HTTP请求获取网页内容。解析网页内容&#xff1a;使用库如BeautifulSoup或lxml来解析HTML内容&#xff0c;提取所需信息。存储数据&#xff…...

TCP、UDP

TCP和UDP的区别 是否面向连接&#xff1a;UDP 在传送数据之前不需要先建立连接。而 TCP 提供面向连接的服务&#xff0c;在传送数据之前必须先建立连接&#xff0c;数据传送结束后要释放连接。 是否是可靠传输&#xff1a;远地主机在收到 UDP 报文后&#xff0c;不需要给出任…...

聊聊暖通空调系统的优化控制方法

目录 暖通空调系统的优化控制方法✈️part1 初版回归网络建模✈️part2 更新的回归网络✈️ 聊聊暖通空调系统的优化控制方法 这篇文章简单分享一下暖通空调&#xff08;HVAC&#xff09;领域常常提到的”优化控制“这一概念指的是什么&#xff0c;它控制的是哪些参数&#…...

2024年合肥市职业院校技能大赛(中职组)赛 网络安任务书样题

2024年合肥市职业院校技能大赛--中职组赛 网络安任务书样题 一、竞赛项目简介&#xff1a;二、竞赛注意事项模块A: 理论技能与职业素养模块B: 网络安全事件响应、数字取证调查和应用安全任务一:应急响应任务二:操作系统取证任务三:网络数据包分析任务四:代码审计 模块C:CTF 夺旗…...

制造企业如何提升项目管理效率?惠科股份选择奥博思PowerProject项目管理系统

全球知名的显示方案综合服务商 - 惠科股份有限公司与北京奥博思达成合作&#xff0c;基于奥博思 PowerProject 搭建企业级项目管理平台。满足惠科多产品多业务领域的项目全周期管理。助力企业在技术研发、产品创新等方面继续取得行业领先优势。 同时&#xff0c;PowerProject …...

mTLS(Mutual TLS)即双向传输层安全,是一种安全通信协议,用于在客户端和服务器之间建立双向的身份验证和加密通道。

mTLS&#xff08;Mutual TLS&#xff09;即双向传输层安全&#xff0c;是一种安全通信协议&#xff0c;用于在客户端和服务器之间建立双向的身份验证和加密通道。在传统的TLS&#xff08;Transport Layer Security&#xff09;中&#xff0c;客户端通常只会验证服务器的身份&am…...

HUAWEI WATCH GT 系列安装第三方应用

文章目录 适用机型概述官方文档从源码构建 hap 文件和对源码签名下载和安装DevEco Studio下载和安装首次启动推荐&#xff1a;设置IDE推荐的兼容版本环境&#xff08;可选&#xff09;安装并启用中文菜单插件 使用DevEco Studio打开项目并进行构建构建问题解决一、生成密钥和证…...

Html jquery下拉select美化插件——selectFilter.js

1. Html jquery下拉select美化插件——selectFilter.js jQuery是一个广泛使用的JavaScript库&#xff0c;它简化了DOM操作、事件处理、动画以及Ajax交互&#xff0c;使得开发者能更高效地构建交互式网页。在本案例中&#xff0c;jquery.selectlist.js插件正是基于jQuery构建的&…...

使用ESP8266扫描WiFi列表

一、简介 准备用基于esp8266的nodemcu开发板做一个天气时钟。目前只实现了第一阶段任务的第一点要求。使用arduino编程&#xff0c;在基于esp8266的nodemcu开发板上实现开机自动连接wifi。 这里记录一下使用ESP8266扫描WiFi列表的方法。还需要研究怎么把列表显示在网页上&…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

微服务通信安全:深入解析mTLS的原理与实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言&#xff1a;微服务时代的通信安全挑战 随着云原生和微服务架构的普及&#xff0c;服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)

第一篇&#xff1a;Liunx环境下搭建PaddlePaddle 3.0基础环境&#xff08;Liunx Centos8.5安装Python3.10pip3.10&#xff09; 一&#xff1a;前言二&#xff1a;安装编译依赖二&#xff1a;安装Python3.10三&#xff1a;安装PIP3.10四&#xff1a;安装Paddlepaddle基础框架4.1…...

DAY 26 函数专题1

函数定义与参数知识点回顾&#xff1a;1. 函数的定义2. 变量作用域&#xff1a;局部变量和全局变量3. 函数的参数类型&#xff1a;位置参数、默认参数、不定参数4. 传递参数的手段&#xff1a;关键词参数5 题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一…...

如何通过git命令查看项目连接的仓库地址?

要通过 Git 命令查看项目连接的仓库地址&#xff0c;您可以使用以下几种方法&#xff1a; 1. 查看所有远程仓库地址 使用 git remote -v 命令&#xff0c;它会显示项目中配置的所有远程仓库及其对应的 URL&#xff1a; git remote -v输出示例&#xff1a; origin https://…...