梦想山人 發表於 2025-12-26 08:47:23

一文秒懂MySQL 的索引下推

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">秒懂 MySQL 索引下推</a></li><li><a href="#_label1">🎯 一句话概括</a></li><li><a href="#_label2">📖 通俗版解释</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_0">没有索引下推(传统方式)</a></li><li><a href="#_lab2_2_1">有了索引下推(优化后)</a></li></ul><li><a href="#_label3">🔧 实际数据库例子</a></li><ul class="second_class_ul"></ul><li><a href="#_label4">💡 核心好处</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_2">1. 减少跑腿次数</a></li><li><a href="#_lab2_4_3">2. 人事小姐姐更聪明了</a></li></ul><li><a href="#_label5">🏷️ 什么情况下能用?</a></li><ul class="second_class_ul"><li><a href="#_lab2_5_4">能用的情况</a></li><li><a href="#_lab2_5_5">不能用的情况</a></li></ul><li><a href="#_label6">🚀 实际效果对比</a></li><ul class="second_class_ul"><li><a href="#_lab2_6_6">测试数据</a></li><li><a href="#_lab2_6_7">查询速度对比</a></li></ul><li><a href="#_label7">🎮 生活化类比</a></li><ul class="second_class_ul"><li><a href="#_lab2_7_8">类比1:图书馆找书</a></li><li><a href="#_lab2_7_9">类比2:外卖筛选</a></li></ul><li><a href="#_label8">📝 简单总结</a></li><ul class="second_class_ul"><li><a href="#_lab2_8_10">三句话记住索引下推</a></li><li><a href="#_lab2_8_11">开启和查看</a></li></ul><li><a href="#_label9">🎯 什么时候最有效?</a></li><ul class="second_class_ul"></ul><li><a href="#_label10">🤔 思考题</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>秒懂 MySQL 索引下推</h2>
<p class="maodian"><a name="_label1"></a></p><h2>🎯 一句话概括</h2>
<p><strong>索引下推就是让索引多干点活,少打扰数据行</strong></p>
<p class="maodian"><a name="_label2"></a></p><h2>📖 通俗版解释</h2>
<p>想象你在一家大公司找员工信息:</p>
<p class="maodian"><a name="_lab2_2_0"></a></p><h3>没有索引下推(传统方式)</h3>
<blockquote><p>你:人事小姐姐,我要找<strong>年龄大于25岁</strong>的所有员工</p>
<p>人事:好的,这是500个符合年龄要求的员工名单(只给了工号)</p>
<p>你:我还需要他们是<strong>北京分公司的</strong></p>
<p>人事:那你自己去查这500个人的详细档案吧</p>
<p>你:😭 我要翻500份档案,一个个看是不是北京分公司的</p></blockquote>
<p><strong>问题</strong>:明明可以在人事那里就过滤掉,非要让你查500次档案</p>
<p class="maodian"><a name="_lab2_2_1"></a></p><h3>有了索引下推(优化后)</h3>
<blockquote><p>你:人事小姐姐,我要找<strong>年龄大于25岁</strong>且是<strong>北京分公司</strong>的员工</p>
<p>人事:好的,我直接帮你筛选,这是80个符合要求的员工名单</p>
<p>你:太好了!我只需要查80份档案</p></blockquote>
<p><strong>效果</strong>:人事(索引)帮你完成了额外筛选,你少查了420次档案</p>
<p class="maodian"><a name="_label3"></a></p><h2>🔧 实际数据库例子</h2>
<div class="jb51code"><pre class="brush:sql;">-- 员工表,索引在 (年龄, 分公司)
CREATE TABLE 员工表 (
    工号 INT PRIMARY KEY,
    姓名 VARCHAR(50),
    年龄 INT,
    分公司 VARCHAR(50),
    工资 DECIMAL(10,2),
    INDEX idx_年龄_分公司 (年龄, 分公司)
);
-- 传统查询(没有索引下推)
SELECT * FROM 员工表
WHERE 年龄 &gt; 25
AND 分公司 LIKE '北京%';
-- 执行过程:
-- 1. 索引找到所有年龄&gt;25的记录(500条)
-- 2. 拿着500个工号去查详细档案(500次)
-- 3. 在500条详细记录中筛选"北京分公司"</pre></div>
<div class="jb51code"><pre class="brush:sql;">-- 开启索引下推后
-- 执行过程:
-- 1. 索引找到所有年龄&gt;25的记录(500条)
-- 2. 索引自己先筛选"分公司 LIKE '北京%'"(剩80条)
-- 3. 只查80个员工的详细档案</pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>💡 核心好处</h2>
<p class="maodian"><a name="_lab2_4_2"></a></p><h3>1. 减少跑腿次数</h3>
<ul><li>原来:跑500次档案室</li><li>现在:跑80次档案室</li><li><strong>节省84%的跑腿时间</strong></li></ul>
<p class="maodian"><a name="_lab2_4_3"></a></p><h3>2. 人事小姐姐更聪明了</h3>
<p>以前人事只做最简单的筛选,现在她能做更多:</p>
<ul><li>✅ 可以判断:<code>分公司 = &#39;北京&#39;</code></li><li>✅ 可以判断:<code>分公司 LIKE &#39;北京%&#39;</code></li><li>✅ 可以判断:<code>年龄 BETWEEN 20 AND 30</code></li><li>❌ 不能判断:<code>工资 &gt; 10000</code>(因为工资信息在档案里)</li></ul>
<p class="maodian"><a name="_label5"></a></p><h2>🏷️ 什么情况下能用?</h2>
<p class="maodian"><a name="_lab2_5_4"></a></p><h3>能用的情况</h3>
<div class="jb51code"><pre class="brush:sql;">-- 情况1:索引里有的信息,人事自己就能判断
-- 索引:(年龄, 城市)
SELECT * FROM 用户
WHERE 年龄 &gt; 20
AND 城市 LIKE '上海%';-- ✅ 能用!城市在索引里
-- 情况2:部分条件在索引里
SELECT * FROM 订单
WHERE 用户ID = 1001
AND 状态 = '已支付';-- ✅ 能用!两个都在索引里</pre></div>
<p class="maodian"><a name="_lab2_5_5"></a></p><h3>不能用的情况</h3>
<div class="jb51code"><pre class="brush:sql;">-- 情况1:要的信息索引里全有,不需要查档案
-- 索引:(姓名, 年龄)
SELECT 姓名, 年龄 FROM 员工;-- ❌ 不需要!直接看名单就行
-- 情况2:条件不在索引里
-- 索引:(年龄, 城市)
SELECT * FROM 用户
WHERE 年龄 &gt; 20
AND 工资 &gt; 10000;-- ❌ 不能用!工资不在索引里</pre></div>
<p class="maodian"><a name="_label6"></a></p><h2>🚀 实际效果对比</h2>
<p class="maodian"><a name="_lab2_6_6"></a></p><h3>测试数据</h3>
<ul><li>员工表:100万条记录</li><li>年龄&gt;25:50万人</li><li>北京分公司:5万人</li></ul>
<p class="maodian"><a name="_lab2_6_7"></a></p><h3>查询速度对比</h3>
<div class="jb51code"><pre class="brush:sql;">传统方式:
✓ 索引扫描:找到50万条记录(很快)
✓ 回表查询:查50万次详细数据(很慢!)
✓ 内存筛选:在50万条里找北京的(一般慢)
⏱️ 总耗时:3.2秒
索引下推:
✓ 索引扫描+筛选:直接找到5万条记录(稍慢一点)
✓ 回表查询:只查5万次详细数据(快很多!)
⏱️ 总耗时:0.8秒</pre></div>
<p><strong>提速4倍!</strong></p>
<p class="maodian"><a name="_label7"></a></p><h2>🎮 生活化类比</h2>
<p class="maodian"><a name="_lab2_7_8"></a></p><h3>类比1:图书馆找书</h3>
<div class="jb51code"><pre class="brush:sql;">传统:图书管理员只按"作者=鲁迅"找书,找到100本
      你一本本翻看是不是"小说类"
下推:告诉管理员"作者=鲁迅 AND 类别=小说"
      直接给你30本小说</pre></div>
<p class="maodian"><a name="_lab2_7_9"></a></p><h3>类比2:外卖筛选</h3>
<div class="jb51code"><pre class="brush:sql;">传统:美团先按"距离&lt;3km"筛选出50家店
      你再一家家看有没有"评分&gt;4.5"
下推:直接搜索"距离&lt;3km AND 评分&gt;4.5"
      直接显示15家符合的店</pre></div>
<p class="maodian"><a name="_label8"></a></p><h2>📝 简单总结</h2>
<p class="maodian"><a name="_lab2_8_10"></a></p><h3>三句话记住索引下推</h3>
<ul><li><strong>让索引多干活</strong>:索引不只是找位置,还能做筛选</li><li><strong>减少回表次数</strong>:筛选好了再查详细数据,少查很多次</li><li><strong>条件要在索引里</strong>:只能筛选索引中包含的条件</li></ul>
<p class="maodian"><a name="_lab2_8_11"></a></p><h3>开启和查看</h3>
<div class="jb51code"><pre class="brush:sql;">-- 默认就是开启的(MySQL 5.6+)
-- 查看有没有用上
EXPLAIN SELECT ...;
-- 看到"Using index condition"就是用了索引下推</pre></div>
<p class="maodian"><a name="_label9"></a></p><h2>🎯 什么时候最有效?</h2>
<table><tbody><tr><th>场景</th><th>效果</th><th>原因</th></tr><tr><td>大表筛选</td><td>⭐⭐⭐⭐⭐</td><td>减少大量回表</td></tr><tr><td>索引选择性高</td><td>⭐⭐⭐⭐</td><td>过滤掉大部分数据</td></tr><tr><td>查询条件多</td><td>⭐⭐⭐</td><td>提前过滤更有效</td></tr><tr><td>小表查询</td><td>⭐</td><td>本来就没多少数据</td></tr></tbody></table>
<p><strong>一句话</strong>:数据量越大,筛选条件越多,索引下推效果越明显!</p>
<p class="maodian"><a name="_label10"></a></p><h2>🤔 思考题</h2>
<p>如果你要查:</p>
<div class="jb51code"><pre class="brush:xhtml;">"年龄&amp;gt;30岁的北京分公司程序员"
</pre></div>
<p>但索引只有&nbsp;<code>(年龄, 分公司)</code>,没有<code>职位</code>字段。</p>
<p>问:索引下推能帮你过滤掉什么?什么过滤不了?</p>
<p><strong>答案</strong>:</p>
<ul><li>✅ 能过滤:年龄&gt;30 且 分公司=北京</li><li>❌ 不能过滤:职位=程序员(需要查了档案才知道)</li></ul>
<p>所以还是会先过滤掉非北京分公司的,再查档案看是不是程序员。</p>
<p>这就是索引下推的核心思想:<strong>能提前过滤的绝不留到后面</strong>!</p>
頁: [1]
查看完整版本: 一文秒懂MySQL 的索引下推