news 2026/9/24 20:09:33

MySQL数据库基础:从建表到索引事务的完整入门实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL数据库基础:从建表到索引事务的完整入门实战

带过不少新人和应届生,发现很多人对“会 MySQL”的定义,就是能跑通几个 select、insert,一旦被问到表结构为什么这样设计、查询为什么慢、事务和索引到底做了什么,就明显露怯。这篇《MySQL 数据库基础》就是写给处于这个阶段的人——不是让你背几条命令就完事,而是把 MySQL 里最核心、最常用、也最容易被忽略的那套基础逻辑一次性理顺。你不需要有任何数据库背景,只要会开电脑,能跟着操作,就可以把它当作第一份入门材料。

我会尽量用“做过项目的人”的口吻来讲,而不是教科书式地罗列知识点。每讲一个概念,我都会告诉你它解决什么问题、实际开发里会怎么用、踩过哪些坑。内容量大,建议你打开电脑边看边操作,效果比干读好得多。

1. 值得先花十分钟搞懂的数据库基本概念

1.1 数据库到底解决了什么问题

很多人说数据库就是“存数据的地方”,这话对,但太笼统了。往深一层想,你用 Excel 也能存数据,为什么企业级应用几乎清一色选 MySQL、PostgreSQL 这类关系型数据库?

原因有四条:持久化、并发控制、数据安全和高效检索。

  • 持久化:进程结束、机器重启,数据不会丢。
  • 并发控制:几百个用户同时读写同一条记录,数据库能保证数据仍然一致。
  • 数据安全:通过账号体系、权限控制、事务机制,避免误操作把数据搞坏。
  • 高效检索:几百万行数据里查一条,有索引的情况下能毫秒级返回。

这四点是文件系统、内存存储很难同时做到的。MySQL 本质上就是一个替你把这些脏活累活全部包掉的服务进程。

1.2 关系型数据库的“关系”二字从哪来

关系型数据库的核心模型是“二维表”,也就是行和列组成的表格。每一行是一条记录,每一列是一个字段,表与表之间通过主键和外键产生关联——这就是“关系”二字的来源。

举个例子,后面我们要做的“学生-课程-成绩”系统:

  • 学生表里存学生的学号、姓名、性别;
  • 课程表里存课程编号、课程名、学分;
  • 成绩表里存学号、课程编号、分数,通过学号和课程编号关联另外两张表。

这样设计的好处是数据不重复:学生的姓名只存在于学生表,课程名只存在于课程表,成绩表只存两个编号加一个分数。这种“不重复存、按需关联”的思路,就是数据库设计里的范式思想。

1.3 SQL 的四大分类,别混着学

SQL(Structured Query Language,结构化查询语言)可以分为四类:

分类全称典型命令作用
DDLData Definition LanguageCREATE、ALTER、DROP定义数据库、表的结构
DMLData Manipulation LanguageINSERT、UPDATE、DELETE操作表里的数据
DQLData Query LanguageSELECT查询数据,日常刷得最多的
DCLData Control LanguageGRANT、REVOKE控制权限

很多初学者一上来就背各种语句,背得混乱,就是因为不知道眼前这条命令属于哪一类。一旦脑子里有这四个分类,你会清楚地知道:改表结构看 DDL,改数据看 DML,查数据看 DQL,授权看 DCL。

1.4 版本和存储引擎:为什么 8.0 成了默认答案

MySQL 的主流版本去年还是 5.7,现在基本已经是 8.0 的天下了。8.0 相比 5.7 多了不少实用特性,比如窗口函数、公共表表达式 CTE、默认字符集改为 utf8mb4,性能也有提升。如果你是新学,直接装 8.0,不要犹豫,更不要为了“兼容老项目”特意去装 5.7——等到你真正需要兼容老项目时,你再回头研究也来得及。

存储引擎方面,你只需要重点关注 InnoDB。它是 MySQL 5.5 之后的默认引擎,支持事务、行级锁、外键、崩溃恢复。而 MyISAM 不支持事务,只支持表级锁,写并发一高就卡。

注意:面试时经常有人问两种引擎的区别。你只要抓住“事务 + 行锁 + 外键”这三个关键词,就抓住了命门。

2. 安装、启动和连上数据库:新手从入门到放弃的三道坎

2.1 版本选择:别下载一堆乱七八糟的版本

很多人在 MySQL 官网下载页看到一堆名词就懵了:MySQL Community Server、MySQL Cluster、MySQL Enterprise。你只需要选MySQL Community Server,这是免费的社区版,个人学习和绝大多数公司生产环境用的都是它。

下载时注意操作系统和位数,Windows 用户通常选 ZIP Archive 或 MSI Installer。MSI 是图形化安装,适合鼠标党;ZIP 是免安装版,解压后手动初始化,适合喜欢掌控每一步的人。macOS 用户可以直接下载 DMG 安装包或通过 Homebrew 安装。

Linux 用户,以 CentOS/Ubuntu 为例,最省心的方式是直接用系统包管理器或 Docker。docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0一条命令就能拉起来一个测试实例,非常适合本地练习。

2.2 初始化、启动服务、设置环境变量

如果你选了免安装版 ZIP,拿到手之后不是解压就能用,必须手动初始化:

# 进入解压后的 bin 目录 mysqld --initialize-insecure

--initialize-insecure的意思是初始化数据目录,并且 root 账号的初始密码为空。如果不用这个参数,MySQL 会生成一个随机密码,新手常常找不到,后面我们单独讲。

初始化完成后启动服务:

# 前端方式启动,适合调试,关掉终端服务就停 mysqld --console # 注册为 Windows 服务 mysqld --install net start mysql

Linux 下常见的是 systemd 方式:

systemctl start mysqld systemctl enable mysqld

启动成功后再把bin目录加入环境变量,这样你在任意目录敲mysql都能进入命令行客户端,不用每次写一长串路径。

2.3 初始密码:网上说得最多的“伪命题”

很多人在搜索栏里敲过“mysql的初始密码是什么”——这里直接告诉你答案:MySQL 根本没有统一初始密码,密码取决于你安装和初始化的方式。

  • 官网 MSI 安装器会在安装过程中让你设置 root 密码;
  • 免安装版用--initialize-insecure,root 密码为空,直接回车即可登录;
  • Linux 用mysqld --initialize,随机密码会写在日志文件里,比如/var/log/mysqld.log,用grep 'temporary password' /var/log/mysqld.log找。

如果 root 密码忘了怎么办?本地测试环境下最常用的做法是“跳过授权表重启”:

# 先在配置文件中临时加一行 skip-grant-tables # 重启 MySQL # 然后免密登录,重设密码 ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';

设置完之后一定要把skip-grant-tables删掉再重启,否则你的 MySQL 等于裸奔,任何人在本机都能免密登录。生产环境千万不要用这招。

2.4 客户端连接:Workbench、Navicat 和 JDBC 的三个小坑

命令行登录没问题之后,很多人喜欢用可视化工具。官方工具是 MySQL Workbench,功能全;Navicat 是很多人习惯用的商业工具,界面友好,连接配置基本一样:主机填127.0.0.1,端口3306,用户名root,密码填你设置过的密码。

连接失败的常见原因有三个:

  • 服务没启动。检查服务状态,而不是反复检查密码。
  • 端口被占用或被防火墙拦截。netstat -ano | findstr 3306(Windows)或lsof -i:3306(macOS/Linux)查看。
  • 密码确实输错了。这个无解,回到 2.3 节重置。

如果你是用 Java 的 JDBC 连接,会额外碰到一个 SSL 相关的问题。8.0 版本的连接串里建议显式加上:

jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true

useSSL=false表示本地开发环境不用 SSL 加密,allowPublicKeyRetrieval=true是配合 MySQL 8.0 默认的 caching_sha2_password 认证方式用的。不加后者会报Public Key Retrieval is not allowed,很多新手卡在这里。

注意:生产环境如果有条件,SSL 该开还是开;这里说的是本地开发调试的便捷配置。

3. 建库建表:以“学生-课程-成绩”为例的实体设计

3.1 字符集和排序规则:别再用 utf8 了

建库时最容易被忽略的是字符集。MySQL 里的utf8实际上是“阉割版”,最多只支持 3 个字节,存不了 emoji 和一些生僻汉字。真正的完整 UTF-8 是utf8mb4,4 个字节,MySQL 8.0 默认字符集已经是它。

建库时建议明确写上:

CREATE DATABASE school DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;

utf8mb4_unicode_ci是排序规则,_ci表示 case insensitive,也就是排序比较时不区分大小写。日常业务用这一套就够稳。

3.2 三张表的设计实战

基于“学生-课程-成绩”场景,我们建三张表。

学生表:

CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '学号', name VARCHAR(50) NOT NULL COMMENT '姓名', gender TINYINT DEFAULT 0 COMMENT '0未知 1男 2女', create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

课程表:

CREATE TABLE course ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '课程编号', course_name VARCHAR(100) NOT NULL COMMENT '课程名', credit DECIMAL(3, 1) NOT NULL DEFAULT 0.0 COMMENT '学分' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

成绩表:

CREATE TABLE score ( id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, course_id INT NOT NULL, score DECIMAL(5, 2) COMMENT '分数', KEY idx_student (student_id), KEY idx_course (course_id), CONSTRAINT fk_score_student FOREIGN KEY (student_id) REFERENCES student (id), CONSTRAINT fk_score_course FOREIGN KEY (course_id) REFERENCES course (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

这里用了两个外键把成绩表跟学生表、课程表关联起来。外键能保证数据的完整性——你不可能往成绩表里插入一个不存在的学生学号。生产环境有些团队为了性能会删掉外键、在应用层做校验,但作为学习者,把外键用明白是非常重要的基础。

3.3 字段类型和默认值:最容易埋雷的地方

建表时类型选错,后期改表的痛苦远超你的想象。我的经验是记住这几个最常见的就够了:

  • 整数:TINYINT(小范围,比如性别)、INT(常规主键)、BIGINT(雪花 ID、大表主键)。
  • 小数:DECIMAL,存钱和分数必须用它,因为它不会出现浮点误差。热词里有个“mysql中int+5”,说的是整数列的算术运算,INT直接加数字没问题,但如果是金额字段,一定不要用FLOAT/DOUBLE,业务上算错一分钱都是事故。
  • 字符串:定长的用CHAR,变长的用VARCHAR。VARCHAR 里写的是字符数上限,不是字节数。
  • 时间:DATETIME存年月日时分秒,DATE只存日期。不要用字符串存时间,否则排序、范围查询都会很难受。

默认值方面,“mysql设置默认值为0”是一个高频搜索词,写法很简单:

status TINYINT NOT NULL DEFAULT 0

我建议所有能用默认值的字段都显式指定默认值,并且在建表时把NOT NULL想清楚。倒不是说每一列都不能为空,而是“能不能为空”这件事必须是你明确设计的,而不是放任自流。否则查询时到处是NULL,统计结果常常对不上。

3.4 表设计阶段最常见的三种错误

  • 不设主键。InnoDB 的表没有显式主键时性能会受影响,而且复制、分表都麻烦。每张表都应该有主键。
  • 字段类型乱用。比如用VARCHAR(1000)存状态码,用TEXT存手机号。类型过大占用更多内存和磁盘,类型过小存不下,都是隐患。
  • 没有统一命名规范。表和字段命名不一致,后来人维护时非常痛苦。我习惯:库名用小写下划线,表名单数,字段名可读性优先,比如create_time而不是ct

4. 增删改查:先把高频 SQL 写对,再谈优化

4.1 INSERT:批量插入比逐条插入更现实

插入三条学生的数据:

INSERT INTO student (name, gender) VALUES ('张三', 1), ('李四', 2), ('王五', 1);

一次插入多条记录,而不是一条条执行,能显著减少客户端和数据库的交互次数。在数据量大的批量初始化场景,这个习惯能省出几倍的时间。

4.2 UPDATE:没写 WHERE 就是事故

更新语句很简单,但最常见的致命错误就是忘写 WHERE:

-- 危险!会把所有学生的性别都改成 1 UPDATE student SET gender = 1; -- 正确做法 UPDATE student SET gender = 1 WHERE id = 2;

很多新手在测试库里没体会,因为数据量小、删错了也能重建。可就因为这样,才更要在练习阶段就养成“先 SELECT 确认范围,再 UPDATE”的习惯:

-- 先查出来看一眼 SELECT * FROM student WHERE id = 2; -- 确认无误再更新 UPDATE student SET gender = 1 WHERE id = 2;

热词里有个“mysql中更新子查询”,说的是 UPDATE 和子查询结合的场景。MySQL 不允许“一边查同一张表一边更新同一张表”,所以像下面这种写法会报错:

-- 报错:You can't specify target table for update in FROM clause UPDATE student SET name = '赵六' WHERE id IN (SELECT student_id FROM score WHERE course_id = 1);

解决办法是包一层临时表:

UPDATE student SET name = '赵六' WHERE id IN ( SELECT * FROM ( SELECT student_id FROM score WHERE course_id = 1 ) AS tmp );

这个问题在业务开发里很常见,值得记住。

4.3 DELETE 和 TRUNCATE:同样是删,命运完全不同

DELETE是逐行删除,可以加 WHERE,操作会记录到 binlog,理论上可以通过事务回滚;TRUNCATE是直接把整张表重建,速度快,但不能回滚。

DELETE FROM student WHERE id = 100; TRUNCATE TABLE student;

注意:如果你只是想清空一张表并让自增 ID 重新从 1 开始,用 TRUNCATE;如果是删掉部分数据,用 DELETE。两者混用的后果是“你以为删干净了,自增 ID 却还从上次的位置往后走”。

4.4 SELECT:WHERE、ORDER BY、LIMIT 的黄金组合

查询是基本功中的基本功。一张成绩表,想查“课程编号为 1 的所有记录,按分数从高到低排”:

SELECT student_id, course_id, score FROM score WHERE course_id = 1 ORDER BY score DESC LIMIT 10;

ORDER BY score DESC是降序,升序用ASC,默认就是升序可以省略。LIMIT 10表示只取前 10 条,分页查询时你会频繁用到它。记住这个组合,已经能覆盖开发中相当大比例的查询需求。

4.5 JOIN:连表查询的理解比背语法更重要

JOIN 相关的搜索一直很热,很多人被 left join、right join、inner join 绕晕。直接说结论:

  • INNER JOIN:只保留两边都能匹配上的记录。
  • LEFT JOIN:左表全部保留,右表能匹配就匹配,匹配不上补 NULL。
  • RIGHT JOIN:右表全部保留,左表匹配不上补 NULL。
  • FULL OUTER JOIN:两边都保留,MySQL 不直接支持,但可以用LEFT JOIN UNION RIGHT JOIN模拟。

套到我们的例子,查“每个学生的选课成绩,包括没选课的学生”:

SELECT s.name, c.course_name, sc.score FROM student s LEFT JOIN score sc ON s.id = sc.student_id LEFT JOIN course c ON sc.course_id = c.id;

LEFT JOIN是因为我们关心“左侧学生表”的全部数据——即使某个学生没有成绩记录,也要显示出来。

面试时还会追一句:JOIN 和子查询怎么选?一般经验是:JOIN 的可读性更好,MySQL 优化器对 JOIN 的优化也比较成熟;子查询在部分场景会出现性能陷阱。能直接用 JOIN 表达的关联需求,优先 JOIN。

4.6 聚合查询:GROUP BY 和 HAVING 的配合

统计“每个学生的平均分,并且只显示平均分大于 60 的学生”:

SELECT student_id, AVG(score) AS avg_score FROM score GROUP BY student_id HAVING avg_score > 60;

注意 WHERE 和 HAVING 的区别:WHERE 是在分组前过滤原始行,HAVING 是在分组聚合后过滤聚合结果。想过滤“平均分大于 60”这种条件,必须用 HAVING,因为 AVG 是在分组阶段才计算出来的。

4.7 一条查询的真实执行顺序

这一点面试极爱考,也是理解 SQL 的钥匙。你写的 SQL 是“先 SELECT 后 FROM”,但数据库实际执行顺序不是这样:

FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY -> LIMIT

也就是说,数据库先确定从哪张表取数据,再过滤行,再分组,再过滤分组,然后才轮到 SELECT 挑选列,最后排序和限制条数。明白这个顺序之后,很多奇怪问题就说得通了——比如为什么 WHERE 里不能直接用 SELECT 里起的别名,因为别名的生成在 WHERE 之后。

5. 索引、事务和存储过程:基础阶段最值得提前了解的进阶点

5.1 索引为什么快:B+ 树的通俗类比

索引本质上是一种“以空间换时间”的数据结构。你可以把它想象成书的目录:没有目录时,你想找某个词只能一页页翻;有目录后,先定位到章节,再缩小范围找。

MySQL InnoDB 里最常用的是 B+ Tree 索引。B+ 树的叶子节点存储数据本身,非叶子节点只存键值和指针。相比二分查找、哈希索引,B+ 树的优势是“矮胖”——三层左右的树就能撑起几百万条数据。

创建索引很简单:

CREATE INDEX idx_score_student ON score(student_id);

但索引不是越多越好。每个索引都要占磁盘,每次插入、更新都要额外维护索引结构。核心原则是:低频查询的字段、区分度低的字段(比如性别)不适合建索引;高频查询条件和 JOIN 关联字段才适合。

5.2 EXPLAIN:看一条查询到底怎么跑

想判断 SQL 有没有走索引,最直接的办法是用 EXPLAIN:

EXPLAIN SELECT * FROM score WHERE student_id = 1;

看输出里的几个关键列:

  • type:从好到坏大致是const>ref>range>index>ALL,看到ALL说明全表扫描,要警惕。
  • key:实际使用的索引名。
  • rows:预估扫描的行数,越小越好。

我见过很多项目上线后突然慢查询,一查就是某个查询没走索引导致几百万行全表扫描。所以不要等出问题再排查,写复杂查询时随手EXPLAIN一下,能发现大量隐患。

5.3 索引失效的几种常见写法

建了索引不代表一定走索引。以下写法在大多数情况下都会让索引失效:

  • 在索引列上做运算:WHERE score + 1 > 60,应改成WHERE score > 59
  • 对索引列隐式类型转换:字段是字符串,条件却写数字。
  • 用前置模糊匹配:WHERE name LIKE '%张%',前缀的%会破坏 B+ 树的按序查找。
  • 联合索引不满足最左前缀原则。

这些不需要死记,只要记住一个底层逻辑:索引能加速的本质是“有序”,一旦你的写法让 MySQL 无法利用这个“有序”,索引就废了。

5.4 事务:ACID 到底在保护什么

事务是数据库的并发安全机制。一个转账操作——从 A 账户扣钱、加到 B 账户——必须作为一个整体,要么都成功,要么都失败,不能只成功一半。

ACID 四个性质:

性质含义通俗理解
A 原子性事务里的操作不可分割要么全做,要么全不做
C 一致性事务前后数据状态合法转账前后总金额不变
I 隔离性并发事务互不干扰我改我的,你查你的
D 持久性提交后修改永久保存重启不丢

MySQL 中事务的用法:

START TRANSACTION; UPDATE account SET balance = balance - 100 WHERE id = 1; UPDATE account SET balance = balance + 100 WHERE id = 2; COMMIT;

如果中间某条语句出错,用ROLLBACK回滚到事务开始前的状态。

隔离级别方面,默认的REPEATABLE READ在绝大多数业务场景都够用,初学者不需要一开始就死磕四种隔离级别的底层实现,但要知道“隔离级别越高,并发性能越差”。

5.5 存储过程:声明语法和适用场景

存储过程就是“把一段 SQL 逻辑预先写好,存到数据库里,调用时直接执行”。基础阶段了解语法即可:

DELIMITER $$ CREATE PROCEDURE GetStudentScore(IN student_id_param INT) BEGIN SELECT s.name, c.course_name, sc.score FROM score sc JOIN student s ON sc.student_id = s.id JOIN course c ON sc.course_id = c.id WHERE s.id = student_id_param; END$$ DELIMITER ;

调用:

CALL GetStudentScore(1);

DELIMITER的作用是把默认的分号结束符临时改成$$,因为存储过程内部有多条 SQL,每条都以分号结尾,如果不改结束符,MySQL 会在第一个分号处认为语句已结束。

实际开发中,存储过程用得越来越少,因为复杂业务逻辑放在应用层更容易调试、测试和版本管理。但你要能看懂别人写的存储过程,而且面试时它也是个高频考点。

6. 基础阶段最值得练的几个排查动作

6.1 锁表了怎么办:show full processlist 的正确用法

“mysql show full processlist”是热词,说明很多人遇到过数据库突然卡住、请求全部堆积的问题。当你怀疑锁表时,第一反应是执行:

SHOW FULL PROCESSLIST;

这个命令会列出当前 MySQL 的所有连接和正在执行的语句。重点关注CommandState列:如果有很多Query长时间卡在Waiting for table metadata lockUpdating,基本可以判断有锁等待问题。

锁一般来自长事务或未提交的更新语句。找到对应的Id后,可以杀掉卡死的会话:

KILL 12345;

不过 KILL 是治标,根本解法是排查业务代码里是否存在“开启事务后长时间不提交”的逻辑。常见的坑是:在事务里调外部接口、写文件、干耗时间,把数据库连接攥在手里不放,导致其他会话全部排队。

6.2 连接不上数据库:从报错关键词倒推原因

新媒体上网一搜,能看到一堆“Navicat 连接不上 MySQL”“PDO 报错”的帖子,其实排查思路大同小异。以常见的 PHP PDO 报错为例:

SQLSTATE[HY000] [2002] Connection refused

这类错误的关键词是Connection refused,基本指向网络层或服务层,而不是密码错误。按顺序检查:

  1. MySQL 服务是否在运行。
  2. 端口是否能访问:telnet 127.0.0.1 3306
  3. 用户是否有远程连接权限:MySQL 默认的 root 用户通常只允许 localhost 连接,远程连接需要单独授权:
CREATE USER 'app'@'%' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON school.* TO 'app'@'%'; FLUSH PRIVILEGES;
  1. 防火墙和云平台安全组是否放行 3306。

如果是密码类错误,报错里通常会写Access denied for user。这类错误先不要反复试,回到第 2 节的重置密码方案处理。

6.3 性能调优从哪个方向下手

“mysql性能调优”是长热词,但基础阶段没必要一上来就啃几百个配置参数。我的建议是按这个顺序排查:

  • 看慢查询日志,找出超过 1 秒的 SQL;
  • 用 EXPLAIN 分析这些 SQL 有没有走索引;
  • 检查连接数是否被打满,应用侧是否合理使用连接池;
  • 表数据量过大时考虑分页优化、归档、分区;
  • 最后才轮到调整innodb_buffer_pool_size这类内存参数。

初学者最容易犯的错误是硬件参数调半天,结果发现罪魁祸首是一条 SQL 没走索引。SQL 层面的问题不解决,配置调得再多也没用。

6.4 怎么检验自己学到了什么

基础学完,最好的检验不是做卷子,而是做一个完整的小项目。比如把我们例子里的“学生-课程-成绩”系统,用一个最简单的 JavaWeb 或 Python 脚本包起来,实现:录入成绩、按学生查成绩单、按课程算平均分、统计不及格人数。

过程中你自然会用到:

  • 数据库连接池(对应热词里的“mysql的数据库连接池”);
  • 事务控制(成绩批量录入时,多条 insert 要么全成功要么全失败);
  • 索引优化(按学生查成绩单时,student_id有没有建索引);
  • 联表查询(成绩单要 join 学生表和课程表)。

这套流程走完,你对 MySQL 的掌握就不是“背了几条命令”,而是“能独立处理一个真实场景”。面试中也能很自信地把表设计、索引、事务、排查链路讲成完整的项目经验。

我在实际教学和带人过程中反复看到,学数据库基础最容易犯的错误不是学不会某个语法,而是没有把“为什么这样设计”想清楚。建表时多深思一层字段类型,写查询时多看一眼执行计划,出问题时先查锁再杀进程——这些小习惯才是从入门走向熟练的真正分水岭。先把这篇文章里的内容动手练熟,再去看优化器和集群相关知识,你会发现后面的一切都建立在今天这些基础上。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 20:08:00

埋点平台选型核心三要素:协议穿透力、计算主权、运维熵值

1. 埋点平台选型不是功能打钩游戏:为什么90%的团队在第二年就推翻重来? 我去年帮三家不同规模的公司做过埋点平台选型,最小的一家是刚融A轮的SaaS初创,最大的是一家年营收超30亿的传统制造企业数字化部门。他们有个惊人共同点&…

作者头像 李华
网站建设 2026/9/24 20:07:05

生成式AI落地智能家居自动化:从规则引擎到意图理解的架构与实践

智能家居这个概念喊了快十年,但真正让我觉得"这玩意儿开始有点意思了",是最近两年生成式AI接入之后的事。以前做智能家居自动化,本质上是在写规则引擎——如果门磁触发且时间在日落后,就开灯;如果温度高于28…

作者头像 李华
网站建设 2026/9/24 20:07:05

StoryDiffusion:四步在本地跑通角色一致漫画生成

StoryDiffusion:四步在本地跑通角色一致漫画生成 【免费下载链接】StoryDiffusion Accepted as [NeurIPS 2024] Spotlight Presentation Paper 项目地址: https://gitcode.com/GitHub_Trending/st/StoryDiffusion StoryDiffusion 是 NeurIPS 2024 论文的开源…

作者头像 李华
网站建设 2026/9/24 20:06:22

数据库DDL设计实战:SchoolDB四张表结构与只导结构导出方法

做数据库这行的,估计都遇到过这种场面:别人伸手问你要表结构,还特意补一句“只要结构,数据一个都不要”。我第一次收到这个需求时,还很认真地回问了一句“要不要把几个常用测试数据也带上,方便你验证&#…

作者头像 李华
网站建设 2026/9/24 20:04:38

自研轻量级SCADA系统全栈实践:通信、实时库、HMI组态与报警引擎

前两年接了一条农产品加工产线的数据采集项目,客户现场用的上位机是一套老牌商用组态软件。功能确实全,但每年的授权费相当可观,点位一超就要再买授权,通信协议是个黑盒,想接自己的算法模块根本无从下手。当时我就下决…

作者头像 李华