<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>Coverage Index｜林鼎淵 Dean Lin</title>
    <link>https://deanlin.net/tags/coverage-index/</link>
    <image><url>https://deanlin.net/images/author_hu_aa256fc934e9a932.jpg</url><title>Coverage Index｜林鼎淵 Dean Lin</title><link>https://deanlin.net/tags/coverage-index/</link><width>144</width><height>144</height></image>
    <description>林鼎淵（Dean Lin）的部落格：生成式 AI 企業內訓講師、外商資安公司軟體專家、7 本書作者。400 多篇文章用白話分享生成式 AI 實戰、Claude Code 與 Vibe Coding 教學、團隊合作與職場成長。</description>
    <generator>Hugo</generator>
    <language>zh-tw</language>
    <copyright>© 2020–2026 林鼎淵 Dean Lin</copyright>
    <lastBuildDate>Fri, 20 Aug 2021 18:27:40 +0800</lastBuildDate>
    <atom:link href="https://deanlin.net/tags/coverage-index/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>你在 Table 建立的 Index 真的有效嗎？用範例帶你理解 Coverage Index 的意義</title>
      <link>https://deanlin.net/blog/202108/covering-index-explained/</link>
      <pubDate>Fri, 20 Aug 2021 18:27:40 +0800</pubDate>
      <guid>https://deanlin.net/blog/202108/covering-index-explained/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>技術教學</category>
      <description>我們會在 Table 中建立 Index 以增加搜尋的效率，但建立 Index 的同時也會影響到資料 insert、update、delete 的效率；所以我們在建立 Index 時需要抱持謹慎的態度，這篇文章將帶大家了解 Coverage Index (覆蓋索引)的意義。</description>
      <media:content url="https://deanlin.net/blog/202108/covering-index-explained/images/covering-index-explained-og_hu_80eae37d512611b0.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<p>我們會在 Table 中建立 Index 以增加搜尋的效率，但建立 Index 的同時也會影響到資料 insert、update、delete 的效率；所以我們在建立 Index 時需要抱持謹慎的態度，這篇文章將帶大家了解 Coverage Index (覆蓋索引)的意義。</p>
<p><img src="https://deanlin.net/blog/202108/covering-index-explained/images/covering-index-explained-01.webp" width="1001" height="566" alt="你在 Table 建立的 Index 真的有效嗎？用範例帶你理解 Coverage Index 的意義（圖 1）" fetchpriority="high" decoding="async"></p>
<h2 id="setp-1建立測試用的-tmp_user-table">SETP 1：建立測試用的 tmp_user Table<a class="h-anchor" href="#setp-1%e5%bb%ba%e7%ab%8b%e6%b8%ac%e8%a9%a6%e7%94%a8%e7%9a%84-tmp_user-table" aria-label="這個段落的連結"></a></h2>
<ol>
<li>id 為 primary key</li>
<li>name 為 index</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff7b72">create</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">table</span><span style="color:#6e7681"> </span>tmp_user<span style="color:#6e7681"> </span>(<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>id<span style="color:#6e7681"> </span>bigint(<span style="color:#a5d6ff">20</span>)<span style="color:#6e7681"> </span><span style="color:#ff7b72">not</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">null</span><span style="color:#6e7681"> </span>auto_increment<span style="color:#6e7681"> </span>,<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>name<span style="color:#6e7681"> </span>varchar(<span style="color:#a5d6ff">255</span>)<span style="color:#6e7681"> </span><span style="color:#ff7b72">not</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">null</span>,<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>password<span style="color:#6e7681"> </span>varchar(<span style="color:#a5d6ff">255</span>)<span style="color:#6e7681"> </span>,<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#ff7b72">index</span><span style="color:#6e7681"> </span>index_name<span style="color:#6e7681"> </span>(name),<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#ff7b72">primary</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">key</span><span style="color:#6e7681"> </span>(id))<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>engine<span style="color:#ff7b72;font-weight:bold">=</span>innodb<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#ff7b72">default</span><span style="color:#6e7681"> </span>character<span style="color:#6e7681"> </span><span style="color:#ff7b72">set</span><span style="color:#ff7b72;font-weight:bold">=</span>utf8<span style="color:#6e7681"> </span><span style="color:#ff7b72">collate</span><span style="color:#ff7b72;font-weight:bold">=</span>utf8_general_ci;<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">insert</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">into</span><span style="color:#6e7681"> </span>tmp_user<span style="color:#6e7681"> </span>(name,<span style="color:#6e7681"> </span>password)<span style="color:#6e7681"> </span><span style="color:#ff7b72">values</span><span style="color:#6e7681"> </span>(<span style="color:#a5d6ff">&#34;寶寶不說&#34;</span>,<span style="color:#a5d6ff">&#34;123&#34;</span>);<span style="color:#6e7681">
</span></span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/be3ceae881d699293cae3e622b31dc1f" rel="noopener">init_user.sql</a>（GitHub Gist）</p>
<hr>
<h2 id="setp-2下-sql-指令了解是否使用-index">SETP 2：下 SQL 指令了解是否使用 Index<a class="h-anchor" href="#setp-2%e4%b8%8b-sql-%e6%8c%87%e4%bb%a4%e4%ba%86%e8%a7%a3%e6%98%af%e5%90%a6%e4%bd%bf%e7%94%a8-index" aria-label="這個段落的連結"></a></h2>
<blockquote>
<p>觀察最後「Extra」欄位的資訊</p>
</blockquote>
<p>➤ SQL A：</p>
<pre tabindex="0"><code>select id from user_table where name= &#39;寶寶不說&#39;
</code></pre><p><img src="https://deanlin.net/blog/202108/covering-index-explained/images/covering-index-explained-02.webp" width="1400" height="162" alt="SETP 2：下 SQL 指令了解是否使用 Index（圖 2）" loading="lazy" decoding="async"></p>
<p>➤ SQL B：</p>
<pre tabindex="0"><code>select password from user_table where name= &#39;寶寶不說&#39;
</code></pre><p><img src="https://deanlin.net/blog/202108/covering-index-explained/images/covering-index-explained-03.webp" width="1400" height="162" alt="SETP 2：下 SQL 指令了解是否使用 Index（圖 3）" loading="lazy" decoding="async"></p>
<hr>
<h2 id="setp-3分析-sql-指令邏輯">SETP 3：分析 SQL 指令邏輯<a class="h-anchor" href="#setp-3%e5%88%86%e6%9e%90-sql-%e6%8c%87%e4%bb%a4%e9%82%8f%e8%bc%af" aria-label="這個段落的連結"></a></h2>
<p>➤ SQL A 分析：</p>
<pre tabindex="0"><code>select id from user_table where name= &#39;寶寶不說&#39;
</code></pre><p>因為 <code>name</code> 有建立 index，所以在查詢到 <code>name</code>後可以直接與 <code>id</code> 對應返回結果；因為 name 已經覆蓋了查詢資料的需求，所以稱為 「Coverage Index」</p>
<p>➤ SQL B 分析：</p>
<pre tabindex="0"><code>select password from user_table where name= &#39;寶寶不說&#39;
</code></pre><p>透過 <code>name</code>找到「寶寶不說」對應的 <code>id</code>，接著透過 <code>id</code>這個 primary key 在 Table 重新輪詢才能取得這一列的完整資料。</p>
<hr>
<h2 id="setp-4建立-coverage-index-優化-sql-b">SETP 4：建立 Coverage Index 優化 SQL B<a class="h-anchor" href="#setp-4%e5%bb%ba%e7%ab%8b-coverage-index-%e5%84%aa%e5%8c%96-sql-b" aria-label="這個段落的連結"></a></h2>
<p>➤ 先將資料庫 drop 掉</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff7b72">drop</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">table</span><span style="color:#6e7681"> </span>tmp_user;<span style="color:#6e7681">
</span></span></span></code></pre></div><p>➤ 重新建立測試資料以及「Coverage Index」</p>
<p>為了避免用 primary key 再次從 Table 查詢的耗能，我們可以把 select 與 where 用到的欄位(name、password)做聯合索引，這樣就能夠直接使用索引查詢而不需用 primary key 重新比對，這就是「Coverage Index」的應用。</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff7b72">create</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">table</span><span style="color:#6e7681"> </span>tmp_user<span style="color:#6e7681"> </span>(<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">   </span>id<span style="color:#6e7681"> </span>bigint(<span style="color:#a5d6ff">20</span>)<span style="color:#6e7681"> </span><span style="color:#ff7b72">not</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">null</span><span style="color:#6e7681"> </span>auto_increment<span style="color:#6e7681"> </span>,<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">   </span>name<span style="color:#6e7681"> </span>varchar(<span style="color:#a5d6ff">255</span>)<span style="color:#6e7681"> </span><span style="color:#ff7b72">not</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">null</span>,<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">   </span>password<span style="color:#6e7681"> </span>varchar(<span style="color:#a5d6ff">255</span>)<span style="color:#6e7681"> </span>,<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">   </span><span style="color:#ff7b72">primary</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">key</span><span style="color:#6e7681"> </span>(id))<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">   </span>engine<span style="color:#ff7b72;font-weight:bold">=</span>innodb<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">   </span><span style="color:#ff7b72">default</span><span style="color:#6e7681"> </span>character<span style="color:#6e7681"> </span><span style="color:#ff7b72">set</span><span style="color:#ff7b72;font-weight:bold">=</span>utf8<span style="color:#6e7681"> </span><span style="color:#ff7b72">collate</span><span style="color:#ff7b72;font-weight:bold">=</span>utf8_general_ci;<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">insert</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">into</span><span style="color:#6e7681"> </span>tmp_user<span style="color:#6e7681"> </span>(name,<span style="color:#6e7681"> </span>password)<span style="color:#6e7681"> </span><span style="color:#ff7b72">values</span><span style="color:#6e7681"> </span>(<span style="color:#a5d6ff">&#34;寶寶不說&#34;</span>,<span style="color:#a5d6ff">&#34;123&#34;</span>);<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">alter</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">table</span><span style="color:#6e7681"> </span>tmp_user<span style="color:#6e7681"> </span><span style="color:#ff7b72">add</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">index</span><span style="color:#6e7681"> </span>name_password(name,password);<span style="color:#6e7681">
</span></span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/d982a22da663e639b01c46ce199b1372" rel="noopener">coverage_example.sql</a>（GitHub Gist）</p>
<p>➤ 再次執行 SQL B：</p>
<pre tabindex="0"><code>explain select password from tmp_user where name = &#39;寶寶不說&#39;;
</code></pre><p>你會發現本次的查詢就有使用到「Index」嚕～</p>
<p><img src="https://deanlin.net/blog/202108/covering-index-explained/images/covering-index-explained-04.webp" width="1400" height="159" alt="SETP 4：建立 Coverage Index 優化 SQL B（圖 4）" loading="lazy" decoding="async"></p>
<hr>
<h2 id="總結">總結<a class="h-anchor" href="#%e7%b8%bd%e7%b5%90" aria-label="這個段落的連結"></a></h2>
<ol>
<li>Index 需要根據實際情境建立</li>
<li>如果查詢會用到多個欄位，建立 Coverage Index 來優化查詢效率</li>
<li>如果資料高達百萬筆，你的 Index 是否有效是非常重要的事情</li>
</ol>
]]></content:encoded>
    </item>
  </channel>
</rss>
