<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>索引 on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/%E7%B4%A2%E5%BC%95/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Thu, 28 Nov 2019 14:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/%E7%B4%A2%E5%BC%95/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>MySQL 实战笔记：安装、事务、索引、锁与高性能优化</title>
      <link>https://ftmao.com/blog/posts/mysql-practical-guide/</link>
      <pubDate>Thu, 28 Nov 2019 14:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/mysql-practical-guide/</guid>
      <description>&lt;h1 id=&#34;mysql-实战笔记安装事务索引锁与高性能优化&#34;&gt;MySQL 实战笔记：安装、事务、索引、锁与高性能优化&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;MySQL 是互联网业务中使用最广泛的关系型数据库之一。掌握它不能只停留在“会写 CRUD”，还要理解事务隔离、索引结构、锁机制以及高性能架构设计。本文从实战出发，结合常见坑点与优化建议，帮你建立系统性的 MySQL 知识地图。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一高层次思想mysql-在解决什么问题&#34;&gt;一、高层次思想：MySQL 在解决什么问题？&lt;/h2&gt;
&lt;p&gt;关系型数据库的核心价值可以概括为三句话：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;持久化&lt;/strong&gt;：让数据安全地落在磁盘上，程序重启不丢失。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一致性&lt;/strong&gt;：通过事务与约束，保证数据始终符合业务规则。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高效访问&lt;/strong&gt;：通过索引、缓存、分区分表等手段，在海量数据中快速读写。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[业务应用] --&amp;gt;|SQL| B[MySQL Server]
    B --&amp;gt; C[SQL 解析 / 优化]
    C --&amp;gt; D[执行引擎]
    D --&amp;gt; E[存储引擎 InnoDB/MyISAM]
    E --&amp;gt; F[Buffer Pool 缓存]
    E --&amp;gt; G[Redo / Undo Log]
    E --&amp;gt; H[磁盘数据文件]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;11-mysql-架构分层&#34;&gt;1.1 MySQL 架构分层&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[连接层] --&amp;gt; B[服务层]
    B --&amp;gt; C[存储引擎层]
    B --&amp;gt; D[查询缓存 / 解析器 / 优化器]
    C --&amp;gt; E[InnoDB 支持事务/行锁]
    C --&amp;gt; F[MyISAM 高速查询/表锁]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;层级&lt;/th&gt;
					&lt;th&gt;职责&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;连接层&lt;/td&gt;
					&lt;td&gt;管理客户端连接、权限验证&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;服务层&lt;/td&gt;
					&lt;td&gt;SQL 解析、优化、执行&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;存储引擎层&lt;/td&gt;
					&lt;td&gt;负责数据的存储与读取&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;12-buffer-poolinnodb-的内存缓存&#34;&gt;1.2 Buffer Pool：InnoDB 的内存缓存&lt;/h3&gt;
&lt;p&gt;Buffer Pool 是 InnoDB 在内存中开辟的一块区域，用来缓存&lt;strong&gt;数据页&lt;/strong&gt;和&lt;strong&gt;索引页&lt;/strong&gt;。它是 MySQL 性能的核心，绝大多数读写操作都先发生在 Buffer Pool 中。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么需要 Buffer Pool？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;磁盘的读写速度比内存慢几个数量级。如果每次查询都读磁盘，性能会极差。Buffer Pool 把热数据放在内存里，大幅减少磁盘 I/O。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Buffer Pool 的工作流程：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant App as 应用
    participant BP as Buffer Pool
    participant Disk as 磁盘

    App-&amp;gt;&amp;gt;BP: 查询 id=1
    BP--&amp;gt;&amp;gt;App: 命中，直接返回
    Note over BP: 数据页已在内存

    App-&amp;gt;&amp;gt;BP: 查询 id=2
    BP-&amp;gt;&amp;gt;Disk: 未命中，从磁盘加载
    Disk--&amp;gt;&amp;gt;BP: 返回数据页
    BP--&amp;gt;&amp;gt;App: 返回数据&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;写数据时的流程：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先把数据页读到 Buffer Pool（如果不在）。&lt;/li&gt;
&lt;li&gt;在 Buffer Pool 中修改数据页，此时这个页变成&lt;strong&gt;脏页（Dirty Page）&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;写 Redo Log（WAL）。&lt;/li&gt;
&lt;li&gt;返回成功给应用。&lt;/li&gt;
&lt;li&gt;后台线程（Page Cleaner）异步把脏页刷回磁盘。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Buffer Pool 的内部结构：&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;结构&lt;/th&gt;
					&lt;th&gt;作用&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;LRU 链表&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;管理数据页的使用热度，最近最少使用的页被淘汰&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Free 链表&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;管理空闲页&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Flush 链表&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;管理脏页，等待后台刷盘&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Change Buffer&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;缓存二级索引的修改，减少随机 I/O&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Adaptive Hash Index&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;自动为热点数据页建立哈希索引，加速查找&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：脏页是异步刷盘的，所以提交成功不代表数据页已经落盘。InnoDB 通过 Redo Log 保证即使崩溃也能恢复。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二安装启动与基础配置&#34;&gt;二、安装、启动与基础配置&lt;/h2&gt;
&lt;h3 id=&#34;21-启动-mysql-服务&#34;&gt;2.1 启动 MySQL 服务&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net start MySQL
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Linux/macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl start mysql&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;22-修改-root-密码&#34;&gt;2.2 修改 root 密码&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ALTER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt; IDENTIFIED &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;23-创建数据库时务必指定编码&#34;&gt;2.3 创建数据库时务必指定编码&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;DATABASE&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;test&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;/*!40100 COLLATE &amp;#39;utf8mb4_bin&amp;#39; */&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #1&lt;/strong&gt;：默认的 &lt;code&gt;utf8&lt;/code&gt; 在 MySQL 中其实是阉割版（最多 3 字节），无法存储 Emoji 等 4 字节字符。生产环境请统一使用 &lt;strong&gt;&lt;code&gt;utf8mb4&lt;/code&gt;&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;24-jdbc-连接串必须带编码与时区&#34;&gt;2.4 JDBC 连接串必须带编码与时区&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jdbc:mysql:&lt;span style=&#34;color:#f92672&#34;&gt;//&lt;/span&gt;127.&lt;span style=&#34;color:#a6e22e&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;1&lt;/span&gt;:3306&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;crmeb_java&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;serverTimeZone&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;UTC&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;useUnicode&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;characterEncoding&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;utf8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;MySQL 8 推荐写法：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jdbc:mysql:&lt;span style=&#34;color:#f92672&#34;&gt;//&lt;/span&gt;127.&lt;span style=&#34;color:#a6e22e&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;1&lt;/span&gt;:3306&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;db_name&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;serverTimezone&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;UTC&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;useSSL&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;useUnicode&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;characterEncoding&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;utf8mb4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #2&lt;/strong&gt;：MySQL 8 默认启用 SSL，但旧版驱动连接时可能报错，可显式设置 &lt;code&gt;useSSL=false&lt;/code&gt;（内网环境）。时区必须指定，否则会出现时间差 8 小时的问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;25-开启通用查询日志&#34;&gt;2.5 开启通用查询日志&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;GLOBAL&lt;/span&gt; general_log &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ON&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;GLOBAL&lt;/span&gt; general_log_file &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/tmp/mysql.log&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SHOW&lt;/span&gt; VARIABLES &lt;span style=&#34;color:#66d9ef&#34;&gt;LIKE&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;general_log%&amp;#34;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #3&lt;/strong&gt;：通用日志会记录所有 SQL，性能开销极大。仅用于临时排查问题，&lt;strong&gt;生产环境不要长期开启&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三存储过程谨慎使用&#34;&gt;三、存储过程：谨慎使用&lt;/h2&gt;
&lt;p&gt;存储过程（Stored Procedure）是把一组 SQL 语句预编译后存储在数据库内部，通过 &lt;code&gt;CALL&lt;/code&gt; 调用的程序单元。它能减少网络往返、封装固定逻辑，但在现代工程实践中已不再被推荐作为首选方案。&lt;/p&gt;
&lt;h3 id=&#34;为什么不推荐重度使用存储过程&#34;&gt;为什么不推荐重度使用存储过程？&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;问题&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;调试困难&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;缺乏现代 IDE 的断点、单步调试和日志追踪能力，定位问题成本高。&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;版本控制弱&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;存储过程游离在应用代码仓库之外，难以做 Code Review 和版本回滚。&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;迁移成本高&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;不同数据库（MySQL、Oracle、SQL Server、PostgreSQL）的存储过程语法差异大，换库时重写代价大。&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;测试困难&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;不易做单元测试、集成测试，CI/CD 流程中难以保证质量。&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;与微服务理念冲突&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;业务逻辑下沉到数据库，导致数据库成为“另一个服务边界”，增加耦合。&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;适合使用存储过程的场景&#34;&gt;适合使用存储过程的场景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;数据迁移与 ETL&lt;/strong&gt;：一次性、数据库内部的数据清洗、转换任务。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;简单的批量操作&lt;/strong&gt;：例如按固定规则批量归档历史数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;强依赖数据库原子性的脚本&lt;/strong&gt;：需要利用数据库事务保证一致性的短时脚本。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;更推荐的替代方案&#34;&gt;更推荐的替代方案&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[复杂业务逻辑] --&amp;gt; B[应用层 / Service 层实现]
    A --&amp;gt; C[ORM / MyBatis 等持久层框架]
    B --&amp;gt; D[便于测试、调试、版本控制]
    C --&amp;gt; D&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;应用层处理&lt;/strong&gt;：把复杂逻辑放在 Java/Go/Python 等服务层，配合事务注解保证一致性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;批量 SQL&lt;/strong&gt;：使用 &lt;code&gt;INSERT ... SELECT&lt;/code&gt; 或 &lt;code&gt;LOAD DATA&lt;/code&gt; 完成批量导入。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;定时任务&lt;/strong&gt;：使用调度框架（如 Quartz、XXL-JOB）替代存储过程做周期化数据处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #4&lt;/strong&gt;：存储过程调试困难、不利于迁移，现代微服务架构中建议&lt;strong&gt;慎用&lt;/strong&gt;。批量数据处理优先考虑在应用层分批插入，或使用 &lt;code&gt;INSERT ... SELECT&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四事务acid-与隔离级别&#34;&gt;四、事务：ACID 与隔离级别&lt;/h2&gt;
&lt;h3 id=&#34;41-事务的-acid-特性&#34;&gt;4.1 事务的 ACID 特性&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[事务] --&amp;gt; B[Atomicity 原子性]
    A --&amp;gt; C[Consistency 一致性]
    A --&amp;gt; D[Isolation 隔离性]
    A --&amp;gt; E[Durability 持久性]
    B --&amp;gt; F[Undo Log]
    E --&amp;gt; G[Redo Log]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;特性&lt;/th&gt;
					&lt;th&gt;含义&lt;/th&gt;
					&lt;th&gt;MySQL 实现&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;原子性&lt;/td&gt;
					&lt;td&gt;要么全成功，要么全回滚&lt;/td&gt;
					&lt;td&gt;Undo Log&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;一致性&lt;/td&gt;
					&lt;td&gt;事务前后数据满足约束&lt;/td&gt;
					&lt;td&gt;约束 + 触发器 + 业务校验&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;隔离性&lt;/td&gt;
					&lt;td&gt;并发事务互不干扰&lt;/td&gt;
					&lt;td&gt;锁 + MVCC&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;持久性&lt;/td&gt;
					&lt;td&gt;提交后数据不丢失&lt;/td&gt;
					&lt;td&gt;Redo Log&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;42-undo-log-与-redo-log&#34;&gt;4.2 Undo Log 与 Redo Log&lt;/h3&gt;
&lt;h4 id=&#34;421-redo-log崩溃恢复与何时返回成功&#34;&gt;4.2.1 Redo Log：崩溃恢复与“何时返回成功”&lt;/h4&gt;
&lt;p&gt;InnoDB 使用 &lt;strong&gt;WAL（Write-Ahead Logging）&lt;/strong&gt; 保证持久性：事务提交前先把修改写到 Redo Log，真正的脏页可以延迟异步刷回磁盘。核心流程如下：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant App as 应用/客户端
    participant MySQL as MySQL Server
    participant BP as Buffer Pool
    participant Redo as Redo Log Buffer / 文件
    participant Disk as 磁盘数据文件

    App-&amp;gt;&amp;gt;MySQL: BEGIN
    App-&amp;gt;&amp;gt;MySQL: UPDATE user SET age=20 WHERE id=1
    MySQL-&amp;gt;&amp;gt;BP: 读取数据页并修改 age=20
    MySQL-&amp;gt;&amp;gt;Redo: 写入 Redo Log：&amp;lt;br/&amp;gt;&amp;#34;将 id=1 的 age 改为 20&amp;#34;
    Note over Redo: WAL：先写日志，再写磁盘
    App-&amp;gt;&amp;gt;MySQL: COMMIT
    MySQL-&amp;gt;&amp;gt;Redo: 按策略刷新 Redo Log
    MySQL--&amp;gt;&amp;gt;App: 返回 Commit 成功
    Note over BP,Disk: 脏页由后台线程异步刷盘&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;Redo 写完后，MySQL 才告诉应用写完成了吗？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;答案是：&lt;strong&gt;默认配置（&lt;code&gt;innodb_flush_log_at_trx_commit = 1&lt;/code&gt;）下，是的。&lt;/strong&gt; MySQL 把 Redo Log &lt;code&gt;fsync&lt;/code&gt; 到磁盘后，才会返回 &lt;code&gt;COMMIT&lt;/code&gt; 成功。&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;参数值&lt;/th&gt;
					&lt;th&gt;提交时的行为&lt;/th&gt;
					&lt;th&gt;持久性&lt;/th&gt;
					&lt;th&gt;典型场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;1（默认）&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;每次提交都 &lt;code&gt;fsync&lt;/code&gt; 刷盘&lt;/td&gt;
					&lt;td&gt;最高，提交即持久&lt;/td&gt;
					&lt;td&gt;生产默认，强一致业务&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;写到 OS Page Cache，每秒刷盘&lt;/td&gt;
					&lt;td&gt;可能丢失 1 秒内数据&lt;/td&gt;
					&lt;td&gt;追求性能，可容忍少量丢失&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;由后台线程每秒刷一次&lt;/td&gt;
					&lt;td&gt;最低，进程崩溃可能丢 1 秒&lt;/td&gt;
					&lt;td&gt;极少使用&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;关键结论&lt;/strong&gt;：默认情况下，应用收到 &lt;code&gt;COMMIT&lt;/code&gt; 成功，就意味着对应事务的 Redo Log 已经持久化到磁盘。此后即使 MySQL 立刻崩溃，重启时也能根据 Redo Log 恢复这条已提交事务；如果崩溃发生在 &lt;code&gt;fsync&lt;/code&gt; 之前，则该事务会被回滚或视为未提交。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;崩溃恢复流程：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[MySQL 崩溃后重启] --&amp;gt; B[加载磁盘 Redo Log]
    B --&amp;gt; C[找到上一次 Checkpoint LSN]
    C --&amp;gt; D[扫描 Checkpoint 之后的 Redo 记录]
    D --&amp;gt; E{Redo 记录对应页&amp;lt;br/&amp;gt;是否需要重放?}
    E --&amp;gt;|Redo LSN &amp;gt; 页 LSN| F[重放该条 Redo]
    F --&amp;gt; G[恢复已提交事务的修改]
    E --&amp;gt;|已落盘，无需重放| H[跳过]
    G --&amp;gt; I[恢复完成，数据库可用]
    H --&amp;gt; I
    J[崩溃时 Redo 尚未 fsync] --&amp;gt; K[事务视为未提交&amp;lt;br/&amp;gt;不会恢复]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：Redo Log 是物理逻辑日志，恢复时按 LSN 顺序重放。InnoDB 会对比 Redo 记录与数据页上的 LSN，避免对已经落盘的页重复应用，保证幂等性。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&#34;422-undo-log回滚是如何实现的&#34;&gt;4.2.2 Undo Log：回滚是如何实现的？&lt;/h4&gt;
&lt;p&gt;Redo 记录“新值”用于崩溃后重做；Undo 记录“旧值”用于事务回滚和 MVCC。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Undo Log 回滚流程：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[事务开始 BEGIN] --&amp;gt; B[执行 UPDATE / DELETE]
    B --&amp;gt; C[生成 Undo Log&amp;lt;br/&amp;gt;记录修改前的旧值]
    C --&amp;gt; D[修改 Buffer Pool 数据页]
    D --&amp;gt; E{事务结果}
    E --&amp;gt;|ROLLBACK| F[读取本事务的 Undo Log]
    F --&amp;gt; G[用旧值覆盖 Buffer Pool 中的修改]
    G --&amp;gt; H[释放事务持有的锁]
    H --&amp;gt; I[事务结束，修改被撤销]
    E --&amp;gt;|COMMIT| J[Redo Log 持久化后提交]
    J --&amp;gt; K[Undo Log 标记为可清理]
    K --&amp;gt; L[Purge 线程异步回收]
    L --&amp;gt; M[事务结束]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;Undo Log 的两个核心作用：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;事务回滚&lt;/strong&gt;：&lt;code&gt;ROLLBACK&lt;/code&gt; 或语句失败时，InnoDB 沿着 Undo Log 把修改逐项撤销，恢复数据到事务开始前的状态，保证原子性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MVCC 一致性读&lt;/strong&gt;：RR/RC 级别下，普通 &lt;code&gt;SELECT&lt;/code&gt; 不加锁，而是通过 Undo Log 链构造事务开始时可见的数据版本（ReadView），实现无锁并发读。&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：Undo Log 的修改本身也受到 Redo Log 保护。崩溃恢复时，Undo Log 页也会通过 Redo Log 重建，否则回滚能力会丢失。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：事务提交后，Undo Log 不会立即删除。如果其他事务还需要用它构造快照，Undo Log 会继续保留，直到没有事务依赖该旧版本后，Purge 线程才会回收。长事务会导致 Undo 堆积、表空间膨胀。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;43-事务的并发问题&#34;&gt;4.3 事务的并发问题&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;问题&lt;/th&gt;
					&lt;th&gt;描述&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;脏读&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;事务 A 读到事务 B 未提交的数据，B 回滚后 A 读到的是脏数据&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;不可重复读&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;事务 A 多次读取同一行，事务 B 修改并提交，导致 A 两次结果不同&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;幻读&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;事务 A 按条件查询一批数据，事务 B 新增/删除满足条件的数据，导致 A 再次查询时结果集不同&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #5&lt;/strong&gt;：不可重复读侧重“修改”，幻读侧重“新增或删除”。InnoDB 默认的可重复读通过 MVCC + 间隙锁（Gap Lock）在很大程度上解决了幻读。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;44-四种隔离级别&#34;&gt;4.4 四种隔离级别&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[读未提交&amp;lt;br&amp;gt;Read Uncommitted] --&amp;gt; B[读已提交&amp;lt;br&amp;gt;Read Committed]
    B --&amp;gt; C[可重复读&amp;lt;br&amp;gt;Repeatable Read]
    C --&amp;gt; D[串行化&amp;lt;br&amp;gt;Serializable]
    style C fill:#e1f5e1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;隔离级别&lt;/th&gt;
					&lt;th&gt;脏读&lt;/th&gt;
					&lt;th&gt;不可重复读&lt;/th&gt;
					&lt;th&gt;幻读&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;读未提交（RU）&lt;/td&gt;
					&lt;td&gt;是&lt;/td&gt;
					&lt;td&gt;是&lt;/td&gt;
					&lt;td&gt;是&lt;/td&gt;
					&lt;td&gt;基本不使用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;读已提交（RC）&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;是&lt;/td&gt;
					&lt;td&gt;是&lt;/td&gt;
					&lt;td&gt;Oracle / SQL Server 默认&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;可重复读（RR）&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;否*&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;MySQL 默认&lt;/strong&gt;，InnoDB 通过 MVCC + Gap Lock 解决幻读&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;串行化（S）&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;否&lt;/td&gt;
					&lt;td&gt;性能最差，完全串行&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #6&lt;/strong&gt;：MySQL 默认是可重复读（RR），但很多互联网项目会改为读已提交（RC），因为 RC 锁粒度更小、并发更高。但改为 RC 后，需要业务层自行处理不可重复读问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五索引类型&#34;&gt;五、索引类型&lt;/h2&gt;
&lt;p&gt;索引是 MySQL 高性能的基石。理解索引类型与适用场景，比单纯记住语法更重要。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[MySQL 索引] --&amp;gt; B[普通索引]
    A --&amp;gt; C[唯一索引]
    A --&amp;gt; D[主键索引]
    A --&amp;gt; E[组合索引]
    A --&amp;gt; F[全文索引]
    D --&amp;gt; G[聚簇索引：数据与索引在一起]
    B --&amp;gt; H[二级索引：叶子节点存主键]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;51-普通索引&#34;&gt;5.1 普通索引&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;INDEX&lt;/span&gt; index_name &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;table&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;column&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;length&lt;/span&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;52-唯一索引&#34;&gt;5.2 唯一索引&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;UNIQUE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;INDEX&lt;/span&gt; indexName &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;table&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;column&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;length&lt;/span&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;53-主键索引&#34;&gt;5.3 主键索引&lt;/h3&gt;
&lt;p&gt;主键索引是一种特殊的唯一索引，一张表只能有一个主键，且不允许为空。&lt;/p&gt;
&lt;h3 id=&#34;54-组合索引&#34;&gt;5.4 组合索引&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;INDEX&lt;/span&gt; idx_name_age &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt;(name, age);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #7&lt;/strong&gt;：组合索引遵循&lt;strong&gt;最左前缀原则&lt;/strong&gt;。&lt;code&gt;idx_name_age&lt;/code&gt; 对 &lt;code&gt;name&lt;/code&gt;、&lt;code&gt;name+age&lt;/code&gt; 有效，但对单独 &lt;code&gt;age&lt;/code&gt; 无效。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;55-全文索引&#34;&gt;5.5 全文索引&lt;/h3&gt;
&lt;p&gt;适用于 &lt;code&gt;LIKE &#39;%关键词%&#39;&lt;/code&gt; 场景，MyISAM 和 InnoDB 5.6+ 都支持。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六锁机制与-mvcc&#34;&gt;六、锁机制与 MVCC&lt;/h2&gt;
&lt;h3 id=&#34;61-共享锁与排他锁&#34;&gt;6.1 共享锁与排他锁&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;锁类型&lt;/th&gt;
					&lt;th&gt;英文&lt;/th&gt;
					&lt;th&gt;读/写&lt;/th&gt;
					&lt;th&gt;兼容性&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;共享锁&lt;/td&gt;
					&lt;td&gt;S Lock / 读锁&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SELECT ... LOCK IN SHARE MODE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;读读兼容，读写互斥&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;排他锁&lt;/td&gt;
					&lt;td&gt;X Lock / 写锁&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt; / 增删改&lt;/td&gt;
					&lt;td&gt;与任何锁都互斥&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[共享锁 S] -- 兼容 --&amp;gt; B[共享锁 S]
    A -- 互斥 --&amp;gt; C[排他锁 X]
    C -- 互斥 --&amp;gt; D[排他锁 X]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #8&lt;/strong&gt;：只有 &lt;code&gt;INSERT / UPDATE / DELETE&lt;/code&gt; 会自动加排他锁；普通 &lt;code&gt;SELECT&lt;/code&gt; 不加锁。如果需要保证读取的是最新已提交数据并防止被修改，应显式使用 &lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;62-mvcc-实现可重复读&#34;&gt;6.2 MVCC 实现可重复读&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant T1 as 事务 A
    participant DB as InnoDB
    participant T2 as 事务 B

    T1-&amp;gt;&amp;gt;DB: START TRANSACTION&amp;lt;br&amp;gt;创建 ReadView
    T2-&amp;gt;&amp;gt;DB: UPDATE row SET x=2&amp;lt;br&amp;gt;并提交
    T1-&amp;gt;&amp;gt;DB: SELECT x&amp;lt;br&amp;gt;仍读取快照中的 x=1
    Note over T1,DB: 事务 A 始终使用开始时的 ReadView&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;MVCC 不是复制一份数据，而是通过 &lt;strong&gt;ReadView + 数据行隐藏字段 + Undo Log 版本链&lt;/strong&gt;，来判断当前事务应该看到哪个版本的数据。&lt;/p&gt;
&lt;h4 id=&#34;621-数据行的两个隐藏字段&#34;&gt;6.2.1 数据行的两个隐藏字段&lt;/h4&gt;
&lt;p&gt;InnoDB 每行数据都有两个隐藏字段：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DB_TRX_ID&lt;/code&gt;：最后修改这行的事务 ID。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DB_ROLL_PTR&lt;/code&gt;：回滚指针，指向这行数据在 Undo Log 中的上一个版本。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;622-readview-里面有什么&#34;&gt;6.2.2 ReadView 里面有什么？&lt;/h4&gt;
&lt;p&gt;ReadView 是一个轻量的结构，不保存任何实际数据，只保存生成时刻的事务状态：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;字段&lt;/th&gt;
					&lt;th&gt;含义&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;m_ids&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;生成 ReadView 时，所有未提交事务的 ID 列表&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;min_trx_id&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;m_ids&lt;/code&gt; 中的最小事务 ID&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;max_trx_id&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;生成 ReadView 时，系统下一个要分配的事务 ID&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;creator_trx_id&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;创建该 ReadView 的事务自身 ID&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&#34;623-可见性判断算法&#34;&gt;6.2.3 可见性判断算法&lt;/h4&gt;
&lt;p&gt;对于查询到的一行数据，取出它的 &lt;code&gt;DB_TRX_ID&lt;/code&gt;，按以下规则判断：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DB_TRX_ID == creator_trx_id&lt;/code&gt;&lt;/strong&gt;：当前事务自己修改的，可见。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DB_TRX_ID &amp;lt; min_trx_id&lt;/code&gt;&lt;/strong&gt;：在 ReadView 创建前已提交，可见。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DB_TRX_ID &amp;gt;= max_trx_id&lt;/code&gt;&lt;/strong&gt;：在 ReadView 创建后才启动的事务修改的，不可见。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;min_trx_id &amp;lt;= DB_TRX_ID &amp;lt; max_trx_id&lt;/code&gt;&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DB_TRX_ID&lt;/code&gt; 在 &lt;code&gt;m_ids&lt;/code&gt; 列表中 → 事务未提交，不可见。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DB_TRX_ID&lt;/code&gt; 不在 &lt;code&gt;m_ids&lt;/code&gt; 列表中 → 事务已提交，可见。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果当前版本不可见，就沿着 &lt;code&gt;DB_ROLL_PTR&lt;/code&gt; 到 Undo Log 链中找上一个版本，重复判断，直到找到可见版本。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[SELECT 读取一行] --&amp;gt; B[获取 DB_TRX_ID]
    B --&amp;gt; C{可见性判断}
    C --&amp;gt;|可见| D[返回当前版本]
    C --&amp;gt;|不可见| E[沿 DB_ROLL_PTR 读 Undo Log 上一个版本]
    E --&amp;gt; C&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h4 id=&#34;624-一个具体例子&#34;&gt;6.2.4 一个具体例子&lt;/h4&gt;
&lt;p&gt;假设 &lt;code&gt;id=1&lt;/code&gt; 的行初始值为 &lt;code&gt;x=1&lt;/code&gt;，事务时间线如下：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;时间&lt;/th&gt;
					&lt;th&gt;事务 10&lt;/th&gt;
					&lt;th&gt;事务 20&lt;/th&gt;
					&lt;th&gt;事务 30（查询）&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;T1&lt;/td&gt;
					&lt;td&gt;开始&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;T2&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;开始&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;T3&lt;/td&gt;
					&lt;td&gt;更新 x=2，未提交&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;T4&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;更新 x=3，未提交&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;T5&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;开始，SELECT x&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;事务 30 生成的 ReadView：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;m_ids = [10, 20]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;min_trx_id = 10&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max_trx_id = 31&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;creator_trx_id = 30&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;查询时，当前行最新版本的 &lt;code&gt;DB_TRX_ID = 20&lt;/code&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;20&lt;/code&gt; 在 &lt;code&gt;m_ids&lt;/code&gt; 中 → 未提交 → 不可见。&lt;/li&gt;
&lt;li&gt;沿 Undo Log 找到上一个版本，&lt;code&gt;DB_TRX_ID = 10&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;10&lt;/code&gt; 在 &lt;code&gt;m_ids&lt;/code&gt; 中 → 未提交 → 不可见。&lt;/li&gt;
&lt;li&gt;再沿 Undo Log 找到初始版本，&lt;code&gt;DB_TRX_ID = 5&lt;/code&gt;（假设为初始插入）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5 &amp;lt; min_trx_id 10&lt;/code&gt; → 已提交 → 可见。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以事务 30 读到的是 &lt;code&gt;x=1&lt;/code&gt;。&lt;/p&gt;
&lt;h4 id=&#34;625-rr-与-rc-的区别&#34;&gt;6.2.5 RR 与 RC 的区别&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RR（可重复读）&lt;/strong&gt;：ReadView 在事务的第一次 SELECT 时创建，之后整个事务复用该 ReadView。因此同一个事务内多次查询结果一致。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RC（读已提交）&lt;/strong&gt;：每次 SELECT 都会创建新的 ReadView，所以能看到其他事务已经提交的最新数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #9&lt;/strong&gt;：RR 级别下，事务开始后创建一致性视图，后续查询都基于该快照。&lt;code&gt;FOR UPDATE&lt;/code&gt; 可以读到最新数据，同时解决第二类更新丢失问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七mysql-优化四大方向&#34;&gt;七、MySQL 优化四大方向&lt;/h2&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[MySQL 优化] --&amp;gt; B[设计层面]
    A --&amp;gt; C[功能层面]
    A --&amp;gt; D[架构层面]
    A --&amp;gt; E[SQL 层面]
    B --&amp;gt; B1[存储引擎 / 字段类型 / 范式]
    C --&amp;gt; C1[索引 / 缓存 / 分区分表]
    D --&amp;gt; D1[主从复制 / 读写分离 / 负载均衡]
    E --&amp;gt; E1[慢 SQL 分析 / 执行计划]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;71-存储引擎选择&#34;&gt;7.1 存储引擎选择&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;引擎&lt;/th&gt;
					&lt;th&gt;特点&lt;/th&gt;
					&lt;th&gt;适用场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;InnoDB&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;支持事务、行锁、外键、崩溃恢复&lt;/td&gt;
					&lt;td&gt;需要数据完整性、高并发的 OLTP 业务&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;MyISAM&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;表锁、无事务、查询和插入速度快&lt;/td&gt;
					&lt;td&gt;读多写少、日志型、临时统计表&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #10&lt;/strong&gt;：MySQL 5.5+ 默认引擎是 InnoDB，新项目&lt;strong&gt;无脑选 InnoDB&lt;/strong&gt;。除非有非常明确的只读/归档场景，否则不要用 MyISAM。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;72-字段类型选择原则&#34;&gt;7.2 字段类型选择原则&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;原则&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;尽可能小&lt;/td&gt;
					&lt;td&gt;能用 &lt;code&gt;INT&lt;/code&gt; 不用 &lt;code&gt;BIGINT&lt;/code&gt;，能用 &lt;code&gt;TINYINT&lt;/code&gt; 不用 &lt;code&gt;INT&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;尽可能定长&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CHAR&lt;/code&gt; 比 &lt;code&gt;VARCHAR&lt;/code&gt; 更适合短定长文本&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;尽可能用整数&lt;/td&gt;
					&lt;td&gt;整数比较和索引效率高于字符串&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;短文本定长&lt;/td&gt;
					&lt;td&gt;用 &lt;code&gt;CHAR&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;短文本变长&lt;/td&gt;
					&lt;td&gt;用 &lt;code&gt;VARCHAR&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;长文本&lt;/td&gt;
					&lt;td&gt;用 &lt;code&gt;TEXT&lt;/code&gt; / &lt;code&gt;BLOB&lt;/code&gt;，避免直接索引大字段&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;73-数据库三大范式&#34;&gt;7.3 数据库三大范式&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[1NF 原子性] --&amp;gt; B[2NF 消除部分依赖]
    B --&amp;gt; C[3NF 消除传递依赖]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;范式&lt;/th&gt;
					&lt;th&gt;核心要求&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;第一范式 1NF&lt;/td&gt;
					&lt;td&gt;字段不可再分，每个字段只存单一值&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;第二范式 2NF&lt;/td&gt;
					&lt;td&gt;非主键字段必须完全依赖主键，不能依赖部分主键&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;第三范式 3NF&lt;/td&gt;
					&lt;td&gt;消除传递依赖，非主键字段只依赖主键&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #11&lt;/strong&gt;：不要过度范式化。互联网业务为了查询性能，常采用&lt;strong&gt;逆范式&lt;/strong&gt;设计，允许适当冗余，用空间换时间。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;74-功能层面优化索引缓存分区分表&#34;&gt;7.4 功能层面优化：索引、缓存、分区分表&lt;/h3&gt;
&lt;p&gt;功能层面优化是在不改变核心业务表结构的前提下，通过索引、缓存、分区分表等手段提升性能。&lt;/p&gt;
&lt;h4 id=&#34;索引优化&#34;&gt;索引优化&lt;/h4&gt;
&lt;p&gt;索引是最常用的功能优化手段。核心原则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WHERE&lt;/code&gt;、&lt;code&gt;JOIN&lt;/code&gt;、&lt;code&gt;ORDER BY&lt;/code&gt; 字段建立索引&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;覆盖索引&lt;/strong&gt;：查询字段都在索引中，避免回表。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最左前缀&lt;/strong&gt;：组合索引按使用频率和字段顺序设计。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;避免索引失效&lt;/strong&gt;：如函数操作索引列、隐式类型转换、前模糊 &lt;code&gt;LIKE&lt;/code&gt;、OR 半边无索引等。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;缓存策略&#34;&gt;缓存策略&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;查询缓存&lt;/strong&gt;：MySQL 8.0 已移除，不建议依赖。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;应用层缓存&lt;/strong&gt;：Redis / Memcached 缓存热点数据，减少数据库压力。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意缓存一致性&lt;/strong&gt;：写数据库后要及时失效或更新缓存，避免脏读。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;分区分表&#34;&gt;分区分表&lt;/h4&gt;
&lt;p&gt;当单表数据量过大（通常超过 500 万 - 1000 万行，或单表超过 10GB）时，需要考虑拆分。主要分为两种：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;方式&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
					&lt;th&gt;对应用是否透明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;分区（Partition）&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;单张表在物理上拆成多个分区文件，逻辑上仍是一张表&lt;/td&gt;
					&lt;td&gt;基本透明，应用按普通表读写&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;分表（Sharding）&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;把数据拆到多张物理表中，如 &lt;code&gt;user_0&lt;/code&gt; - &lt;code&gt;user_15&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;不透明，通常需要分库分表中间件或应用层路由&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h5 id=&#34;分区partition&#34;&gt;分区（Partition）&lt;/h5&gt;
&lt;p&gt;分区是 MySQL 提供的原生功能，一张逻辑表由多个物理分区组成，每个分区独立存储。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;常见分区类型：&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;类型&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
					&lt;th&gt;适用场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;RANGE&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;按连续范围分区，如按时间、ID 范围&lt;/td&gt;
					&lt;td&gt;日志表、订单表按月份归档&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;LIST&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;按离散值列表分区&lt;/td&gt;
					&lt;td&gt;按地区、状态等枚举值&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;HASH&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;按分区键哈希取模&lt;/td&gt;
					&lt;td&gt;数据分布均匀，无业务热点&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;KEY&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;类似 HASH，但由 MySQL 内部决定哈希函数&lt;/td&gt;
					&lt;td&gt;简化使用&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;创建分区表示例（RANGE）：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt; user_log (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    id BIGINT &lt;span style=&#34;color:#66d9ef&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    user_id BIGINT &lt;span style=&#34;color:#66d9ef&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    action VARCHAR(&lt;span style=&#34;color:#ae81ff&#34;&gt;50&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created_at DATETIME &lt;span style=&#34;color:#66d9ef&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NULL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;) PARTITION &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; RANGE (&lt;span style=&#34;color:#66d9ef&#34;&gt;YEAR&lt;/span&gt;(created_at)) (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PARTITION p2022 &lt;span style=&#34;color:#66d9ef&#34;&gt;VALUES&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;LESS&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;THAN&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;2023&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PARTITION p2023 &lt;span style=&#34;color:#66d9ef&#34;&gt;VALUES&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;LESS&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;THAN&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;2024&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PARTITION p2024 &lt;span style=&#34;color:#66d9ef&#34;&gt;VALUES&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;LESS&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;THAN&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;2025&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PARTITION pfuture &lt;span style=&#34;color:#66d9ef&#34;&gt;VALUES&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;LESS&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;THAN&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;MAXVALUE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;分区表的增删改查：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 查询整个表（和普通表一样）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; user_log &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; created_at &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2024-01-01&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 指定分区查询（强制扫描某个分区）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; user_log PARTITION (p2024) &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; action &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;login&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 插入数据（MySQL 自动根据分区键路由）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;INSERT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;INTO&lt;/span&gt; user_log &lt;span style=&#34;color:#66d9ef&#34;&gt;VALUES&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;10086&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;login&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2024-06-01 10:00:00&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 更新数据（如果修改分区键，可能需要跨分区移动行）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;UPDATE&lt;/span&gt; user_log &lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; created_at &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2025-01-01&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 删除整个分区的数据（比分批 DELETE 快得多）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ALTER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt; user_log &lt;span style=&#34;color:#66d9ef&#34;&gt;DROP&lt;/span&gt; PARTITION p2022;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;分区表的关键点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;分区键必须包含在唯一索引/主键中&lt;/strong&gt;。例如主键是 &lt;code&gt;(id)&lt;/code&gt;，那么不能按 &lt;code&gt;created_at&lt;/code&gt; 分区，除非主键改成 &lt;code&gt;(id, created_at)&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;查询要命中分区键才能裁剪&lt;/strong&gt;。如果 &lt;code&gt;WHERE&lt;/code&gt; 里没有分区键，MySQL 会扫描所有分区，反而更慢。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分区数量不宜过多&lt;/strong&gt;。MySQL 官方建议单表分区数控制在 1000 以内，过多会消耗文件描述符和内存。&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;分表sharding&#34;&gt;分表（Sharding）&lt;/h5&gt;
&lt;p&gt;分表是把一张逻辑表拆成多张物理表，通常需要配合分库分表中间件（如 ShardingSphere、MyCat）或应用层路由。&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;拆分方式&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
					&lt;th&gt;适用场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;垂直拆分&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;按业务/字段拆分，如 &lt;code&gt;user_base&lt;/code&gt; 和 &lt;code&gt;user_profile&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;单表字段过多、冷热数据分离&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;水平拆分&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;按行拆分，如 &lt;code&gt;user_id % 16&lt;/code&gt; 分 16 张表&lt;/td&gt;
					&lt;td&gt;单表数据量过大、并发过高&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;水平拆分策略：&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;策略&lt;/th&gt;
					&lt;th&gt;优点&lt;/th&gt;
					&lt;th&gt;缺点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;范围分片&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;按时间/ID 范围，扩容简单&lt;/td&gt;
					&lt;td&gt;容易热点，如最新时间片集中写入&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;哈希分片&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;数据分布均匀&lt;/td&gt;
					&lt;td&gt;扩容需要迁移数据&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;一致性哈希&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;扩容时迁移数据量少&lt;/td&gt;
					&lt;td&gt;实现稍复杂&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;列表分片&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;按地区/类型等枚举值&lt;/td&gt;
					&lt;td&gt;适合有明显业务边界的数据&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;分库分表带来的问题：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;分布式事务&lt;/strong&gt;：跨库事务无法靠单机 ACID 保证。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跨库 JOIN&lt;/strong&gt;：需要在应用层聚合，或反范式冗余字段。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全局唯一 ID&lt;/strong&gt;：不能用自增主键，需要雪花算法、号段等方案。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分页排序&lt;/strong&gt;：&lt;code&gt;ORDER BY&lt;/code&gt; + &lt;code&gt;LIMIT&lt;/code&gt; 跨多表后合并复杂。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据迁移&lt;/strong&gt;：扩容时需要平滑迁移历史数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #14&lt;/strong&gt;：不要为了拆分而拆分。大多数业务先做好索引、SQL 优化、加缓存，单表撑到千万级没问题。拆分成本：分区 &amp;lt; 分表 &amp;lt; 分库。优先考虑分区；分区也撑不住时，再考虑分库分表。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;75-sql-层面优化慢-sql-分析与执行计划&#34;&gt;7.5 SQL 层面优化：慢 SQL 分析与执行计划&lt;/h3&gt;
&lt;p&gt;SQL 层面的优化收益往往最高，因为一条烂 SQL 可以把整个数据库拖垮。&lt;/p&gt;
&lt;h4 id=&#34;如何发现慢-sql&#34;&gt;如何发现慢 SQL&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;慢查询日志&lt;/strong&gt;：&lt;code&gt;slow_query_log = ON&lt;/code&gt;，&lt;code&gt;long_query_time&lt;/code&gt; 设置阈值。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;performance_schema&lt;/strong&gt;：MySQL 内置性能监控。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pt-query-digest&lt;/strong&gt;：Percona Toolkit 分析慢日志。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;应用层 APM&lt;/strong&gt;：SkyWalking、Pinpoint 等追踪 SQL 耗时。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;explain-看执行计划&#34;&gt;EXPLAIN 看执行计划&lt;/h4&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;EXPLAIN&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; age &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;18&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; created_at &lt;span style=&#34;color:#66d9ef&#34;&gt;LIMIT&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;关键字段：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;字段&lt;/th&gt;
					&lt;th&gt;含义&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;访问类型，越靠前越好：&lt;code&gt;system &amp;gt; const &amp;gt; eq_ref &amp;gt; ref &amp;gt; range &amp;gt; index &amp;gt; ALL&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;key&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;实际使用的索引&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;rows&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;预估扫描行数&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;Extra&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;额外信息&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;type&lt;/code&gt; 详解：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;type&lt;/code&gt; 表示 MySQL 访问表的方式，可以理解为“查资料时翻书的方式”。&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;type&lt;/th&gt;
					&lt;th&gt;通俗解释&lt;/th&gt;
					&lt;th&gt;效率&lt;/th&gt;
					&lt;th&gt;典型 SQL&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;system&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;表里最多 1 条数据，直接当常量&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;查只有一条配置的配置表&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;const&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;通过主键/唯一索引等值查，最多 1 条&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;WHERE id = 1&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;eq_ref&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;JOIN 时，被驱动表用主键/唯一索引匹配，最多 1 条&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;A JOIN B ON A.b_id = B.id&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;ref&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;通过普通索引等值查，可能有多条&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;WHERE phone = &#39;xxx&#39;&lt;/code&gt;（phone 是普通索引）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;range&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;索引范围扫描&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;WHERE age &amp;gt; 18&lt;/code&gt;、&lt;code&gt;BETWEEN&lt;/code&gt;、&lt;code&gt;IN&lt;/code&gt;、&lt;code&gt;LIKE &#39;prefix%&#39;&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;index&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;全索引扫描&lt;/td&gt;
					&lt;td&gt;⭐⭐&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SELECT 索引列 FROM 表&lt;/code&gt;、按索引排序&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;ALL&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;全表扫描&lt;/td&gt;
					&lt;td&gt;⭐&lt;/td&gt;
					&lt;td&gt;没走索引，逐行读&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;各 type 详细说明与示例：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. system：表本身就是常量&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;表里只有 0 条或 1 条数据，MySQL 把它当成常量处理。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; system_config;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;如果 &lt;code&gt;system_config&lt;/code&gt; 只有一条记录，EXPLAIN 可能看到 &lt;code&gt;type = system&lt;/code&gt;。实际业务表中很少见。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. const：精确命中唯一值&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过主键或唯一索引做等值查询，最多返回 1 行。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- id 是主键
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10086&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- phone 是唯一索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; phone &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;13800138000&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;这是单表查询里最好的 type。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. eq_ref：JOIN 中的 const&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;多表 JOIN 时，被驱动表通过主键或唯一索引与驱动表匹配，每次匹配最多返回 1 行。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; o.&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;, u.name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;JOIN&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; u &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; o.user_id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; u.id;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;假设 &lt;code&gt;user.id&lt;/code&gt; 是主键，&lt;code&gt;order&lt;/code&gt; 表的每一行去 &lt;code&gt;user&lt;/code&gt; 表查都是精确命中 1 行，此时 &lt;code&gt;user&lt;/code&gt; 表的 &lt;code&gt;type = eq_ref&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. ref：普通索引等值查询&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过普通索引（非唯一索引）做等值查询，可能返回多条。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- status 是普通索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; status &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;PAID&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;code&gt;status = &#39;PAID&#39;&lt;/code&gt; 可能对应很多订单。这是生产环境最常见的良好 type。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. range：索引范围扫描&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;使用索引做范围查询。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- age 有索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; age &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;18&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- create_time 有索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; create_time &lt;span style=&#34;color:#66d9ef&#34;&gt;BETWEEN&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2024-01-01&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2024-01-31&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- id 是主键
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#66d9ef&#34;&gt;IN&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- phone 有索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; phone &lt;span style=&#34;color:#66d9ef&#34;&gt;LIKE&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1380%&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;注意：&lt;code&gt;LIKE &#39;1380%&#39;&lt;/code&gt; 走 range；&lt;code&gt;LIKE &#39;%1380&#39;&lt;/code&gt; 或 &lt;code&gt;LIKE &#39;%1380%&#39;&lt;/code&gt; 会退化成 ALL。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. index：全索引扫描&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;遍历整个索引树，而不是全表扫描数据。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- name 是索引列
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; name &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 按索引列排序
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; id &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; id;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;因为索引通常比实际数据小，读索引比读整行快。但如果查询列不在索引里或需要大量回表，index 也会很慢。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7. ALL：全表扫描&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;没有用到索引，逐行读取整张表。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- phone 没有索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; phone &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;13800138000&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 对索引列使用函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; DATE(create_time) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2024-01-01&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 前模糊 LIKE
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; phone &lt;span style=&#34;color:#66d9ef&#34;&gt;LIKE&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;%1380%&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;生产环境出现 &lt;code&gt;type = ALL&lt;/code&gt; 通常需要优化。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;简单记忆口诀：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;system/const 是精确，一行数据最省事；
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;eq_ref 是 JOIN 版 const，主键关联一对一；
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ref 普通索引等值查，可能返回好几行；
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;range 范围扫描用得广，BETWEEN IN 都能上；
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index 全扫索引比表强；
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ALL 全表扫描要提防。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;生产环境建议：&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;type&lt;/th&gt;
					&lt;th&gt;是否需要关注&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;system / const / eq_ref / ref&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;优秀，基本不用管&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;range&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;正常，注意范围不要太大&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;index&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;需要警惕，确认是否真的需要全索引扫描&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ALL&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;必须优化，除非表很小（几万行以内）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;一般原则：单表查询尽量做到 &lt;code&gt;ref&lt;/code&gt; 或更好，范围查询 &lt;code&gt;range&lt;/code&gt; 可接受，尽量避免 &lt;code&gt;ALL&lt;/code&gt; 和大量数据的 &lt;code&gt;index&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;危险的 Extra：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Using filesort&lt;/code&gt;：需要额外排序，常见于无索引的 &lt;code&gt;ORDER BY&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Using temporary&lt;/code&gt;：需要创建临时表，常见于 &lt;code&gt;GROUP BY&lt;/code&gt;、&lt;code&gt;DISTINCT&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Using index&lt;/code&gt;：好现象，使用了覆盖索引。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Using where&lt;/code&gt;：在存储引擎返回数据后再过滤。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;典型慢-sql-写法与严重踩坑案例&#34;&gt;典型慢 SQL 写法与严重踩坑案例&lt;/h4&gt;
&lt;h5 id=&#34;案例-1select-&#34;&gt;案例 1：&lt;code&gt;SELECT *&lt;/code&gt;&lt;/h5&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; user_id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10086&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：读取不需要的列，增加网络传输和 Buffer Pool 占用，容易触发回表。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优化&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; order_id, status, amount &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; user_id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10086&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h5 id=&#34;案例-2前模糊-like-导致索引失效&#34;&gt;案例 2：前模糊 LIKE 导致索引失效&lt;/h5&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; phone &lt;span style=&#34;color:#66d9ef&#34;&gt;LIKE&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;%1380%&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：&lt;code&gt;%&lt;/code&gt; 在开头无法使用 B+ 树索引，会全表扫描。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优化&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;改为后缀匹配：&lt;code&gt;LIKE &#39;1380%&#39;&lt;/code&gt;（如果有索引仍可用）。&lt;/li&gt;
&lt;li&gt;使用全文索引或 Elasticsearch。&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;案例-3or-条件半边无索引&#34;&gt;案例 3：&lt;code&gt;OR&lt;/code&gt; 条件半边无索引&lt;/h5&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; phone &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;13800138000&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;OR&lt;/span&gt; email &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;a@b.com&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：如果 &lt;code&gt;email&lt;/code&gt; 没有索引，MySQL 可能放弃索引，直接全表扫描。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优化&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; phone &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;13800138000&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;UNION&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ALL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; email &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;a@b.com&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;或给 &lt;code&gt;email&lt;/code&gt; 也建索引。&lt;/p&gt;
&lt;h5 id=&#34;案例-4隐式类型转换&#34;&gt;案例 4：隐式类型转换&lt;/h5&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; phone &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;13800138000&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：&lt;code&gt;phone&lt;/code&gt; 是 &lt;code&gt;varchar&lt;/code&gt;，MySQL 会先把所有行的 &lt;code&gt;phone&lt;/code&gt; 转成整数再比较，索引失效。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优化&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; phone &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;13800138000&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h5 id=&#34;案例-5函数操作索引列&#34;&gt;案例 5：函数操作索引列&lt;/h5&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; DATE(create_time) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2024-01-01&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：对索引列使用函数，&lt;code&gt;DATE(create_time)&lt;/code&gt; 不是索引本身，索引失效。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优化&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; create_time &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2024-01-01&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; create_time &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2024-01-02&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h5 id=&#34;案例-6大-offset-深分页&#34;&gt;案例 6：大 OFFSET 深分页&lt;/h5&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; id &lt;span style=&#34;color:#66d9ef&#34;&gt;LIMIT&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1000000&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：MySQL 需要先扫描 1000010 行，再扔掉前面的 1000000 行，越往后越慢。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优化&lt;/strong&gt;（延迟关联）：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; o.&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;JOIN&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; id &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; id &lt;span style=&#34;color:#66d9ef&#34;&gt;LIMIT&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1000000&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;) tmp &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; o.id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; tmp.id;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;或记录上次位置：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; id &lt;span style=&#34;color:#66d9ef&#34;&gt;LIMIT&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h5 id=&#34;案例-7in-子句元素过多&#34;&gt;案例 7：&lt;code&gt;IN&lt;/code&gt; 子句元素过多&lt;/h5&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#66d9ef&#34;&gt;IN&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, ..., &lt;span style=&#34;color:#ae81ff&#34;&gt;50000&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：IN 元素过多会导致解析和执行效率下降，甚至超出限制。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优化&lt;/strong&gt;：分批查询，或把 ID 写入临时表再 JOIN。&lt;/p&gt;
&lt;h5 id=&#34;案例-8大事务长时间持有锁&#34;&gt;案例 8：大事务长时间持有锁&lt;/h5&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;START&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TRANSACTION&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 大量更新操作
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;UPDATE&lt;/span&gt; huge_table &lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; ... &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; ...;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 业务逻辑处理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 几分钟后才 COMMIT&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：长时间持有行锁/间隙锁，阻塞其他事务，Undo Log 堆积，主从延迟放大。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优化&lt;/strong&gt;：拆分为小批量事务，减少单次锁定范围。&lt;/p&gt;
&lt;h4 id=&#34;线上最严重的几个踩坑&#34;&gt;线上最严重的几个踩坑&lt;/h4&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;踩坑行为&lt;/th&gt;
					&lt;th&gt;后果&lt;/th&gt;
					&lt;th&gt;正确做法&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;UPDATE / DELETE&lt;/code&gt; 忘记写 &lt;code&gt;WHERE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;全表数据被改/删，可能导致业务瘫痪&lt;/td&gt;
					&lt;td&gt;先 &lt;code&gt;SELECT&lt;/code&gt; 确认影响行数，使用 &lt;code&gt;LIMIT&lt;/code&gt;，小批量执行&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;高峰期执行 &lt;code&gt;ALTER TABLE&lt;/code&gt; / &lt;code&gt;OPTIMIZE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;锁表，查询堆积，服务雪崩&lt;/td&gt;
					&lt;td&gt;使用 Online DDL（如 &lt;code&gt;pt-online-schema-change&lt;/code&gt;），低峰期执行&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;直接 &lt;code&gt;SELECT * FROM huge_table&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;打满 Buffer Pool，拖垮数据库&lt;/td&gt;
					&lt;td&gt;加分页、加条件、只查必要字段&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;慢 SQL 打满连接池&lt;/td&gt;
					&lt;td&gt;应用无法获取连接，全面超时&lt;/td&gt;
					&lt;td&gt;设置 SQL 超时，连接池隔离，熔断降级&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #15&lt;/strong&gt;：上线任何 SQL 前，先用 &lt;code&gt;EXPLAIN&lt;/code&gt; 检查执行计划。看到 &lt;code&gt;type = ALL&lt;/code&gt;、&lt;code&gt;Extra = Using filesort&lt;/code&gt; 或 &lt;code&gt;Using temporary&lt;/code&gt; 时，必须优化后再上线。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八高性能架构设计&#34;&gt;八、高性能架构设计&lt;/h2&gt;
&lt;h3 id=&#34;81-主从复制--读写分离&#34;&gt;8.1 主从复制 + 读写分离&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[写请求] --&amp;gt; B[主库 Master]
    B --&amp;gt;|binlog 同步| C[从库 Slave 1]
    B --&amp;gt;|binlog 同步| D[从库 Slave 2]
    E[读请求] --&amp;gt; C
    E --&amp;gt; D&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #12&lt;/strong&gt;：主从复制存在延迟。如果对实时性要求极高（如支付后立刻查询余额），读请求应强制走主库，或在业务层做延迟容忍设计。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;82-分区分表&#34;&gt;8.2 分区分表&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;方式&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;垂直拆分&lt;/td&gt;
					&lt;td&gt;按业务/字段拆分，如用户表拆成 &lt;code&gt;user_base&lt;/code&gt; 和 &lt;code&gt;user_profile&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;水平拆分&lt;/td&gt;
					&lt;td&gt;按行拆分，如按 &lt;code&gt;user_id % 16&lt;/code&gt; 分 16 张表&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九用户权限与数据导出&#34;&gt;九、用户权限与数据导出&lt;/h2&gt;
&lt;h3 id=&#34;91-创建新用户并授权&#34;&gt;9.1 创建新用户并授权&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 创建用户
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;USER&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;goose_vod&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;%&amp;#39;&lt;/span&gt; IDENTIFIED &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;xxxx&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 授权
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;GRANT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ALL&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;PRIVILEGES&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;ad_db&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;.&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TO&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;goose_vod&lt;span style=&#34;color:#f92672&#34;&gt;`@`%`&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 刷新权限
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FLUSH &lt;span style=&#34;color:#66d9ef&#34;&gt;PRIVILEGES&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #13&lt;/strong&gt;：生产环境请遵循最小权限原则，不要给业务账号 &lt;code&gt;ALL PRIVILEGES&lt;/code&gt;。例如只读账号只授予 &lt;code&gt;SELECT&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;92-导出数据库&#34;&gt;9.2 导出数据库&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mysqldump -h xxxx-rds.xxxx.us-east-1.rds.amazonaws.com &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -u goose_vod -p appstore_db &amp;gt; ~/database_dump.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;十避坑清单速查表&#34;&gt;十、避坑清单速查表&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;编号&lt;/th&gt;
					&lt;th&gt;避坑点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;数据库字符集用 &lt;code&gt;utf8mb4&lt;/code&gt;，不要用默认 &lt;code&gt;utf8&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;JDBC 连接串指定 &lt;code&gt;serverTimezone&lt;/code&gt; 和 &lt;code&gt;characterEncoding&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;通用日志只用于临时排查，不要长期开启&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;4&lt;/td&gt;
					&lt;td&gt;存储过程谨慎使用，优先应用层处理业务逻辑&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;5&lt;/td&gt;
					&lt;td&gt;不可重复读 ≠ 幻读，RR 级别下 InnoDB 基本解决幻读&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;6&lt;/td&gt;
					&lt;td&gt;根据业务决定是否将隔离级别从 RR 改为 RC&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;7&lt;/td&gt;
					&lt;td&gt;组合索引遵循最左前缀原则&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;8&lt;/td&gt;
					&lt;td&gt;普通 &lt;code&gt;SELECT&lt;/code&gt; 不加锁，需要锁时显式 &lt;code&gt;FOR UPDATE&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;9&lt;/td&gt;
					&lt;td&gt;RR 下快照读基于 ReadView，&lt;code&gt;FOR UPDATE&lt;/code&gt; 读最新数据&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;10&lt;/td&gt;
					&lt;td&gt;新项目默认使用 InnoDB，不要选 MyISAM&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;11&lt;/td&gt;
					&lt;td&gt;适度逆范式，用空间换查询时间&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;12&lt;/td&gt;
					&lt;td&gt;主从延迟存在，实时读考虑强制走主库&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;13&lt;/td&gt;
					&lt;td&gt;生产环境遵循最小权限原则&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;14&lt;/td&gt;
					&lt;td&gt;不要为了拆分而拆分；拆分成本：分区 &amp;lt; 分表 &amp;lt; 分库，优先考虑分区&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;15&lt;/td&gt;
					&lt;td&gt;上线前用 EXPLAIN 检查执行计划，警惕 ALL / filesort / temporary&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十一总结&#34;&gt;十一、总结&lt;/h2&gt;
&lt;p&gt;MySQL 的学习路径可以概括为：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[熟练 SQL 与安装配置] --&amp;gt; B[理解事务与隔离级别]
    B --&amp;gt; C[掌握索引设计与优化]
    C --&amp;gt; D[理解锁与 MVCC]
    D --&amp;gt; E[掌握主从复制与读写分离]
    E --&amp;gt; F[持续分析慢 SQL 与执行计划]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;高性能 MySQL 没有银弹，核心在于：&lt;strong&gt;合理的表结构设计、精准的索引、恰到好处的事务隔离、以及能够水平扩展的架构&lt;/strong&gt;。希望这份笔记能成为你日常开发与面试复习的速查手册。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;参考&#34;&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.cnblogs.com/zhangkanghui/p/9613844.html&#34;&gt;MySQL 5.7 安装教程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.cnblogs.com/sharpest/p/10390035.html&#34;&gt;MySQL 优化四大方面&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.csdn.net/weixin_43895671/article/details/107402521&#34;&gt;MySQL 锁与事务详解&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
  </channel>
</rss>
