<?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/">
  <channel>
    <title>Index on Chanyeol Dev</title>
    <link>https://chanyeols.com/tags/index/</link>
    <description>Recent content in Index on Chanyeol Dev</description>
    <generator>Hugo</generator>
    <language>ko-kr</language>
    <lastBuildDate>Tue, 24 Feb 2026 09:00:00 +0900</lastBuildDate>
    <atom:link href="https://chanyeols.com/tags/index/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>MySQL 인덱스 최적화 전략: 느린 쿼리를 100배 빠르게 만드는 마법</title>
      <link>https://chanyeols.com/posts/mysql-index-optimization/</link>
      <pubDate>Tue, 24 Feb 2026 09:00:00 +0900</pubDate>
      <guid>https://chanyeols.com/posts/mysql-index-optimization/</guid>
      <description>&lt;h2 id=&#34;1-서론-인덱스는-왜-중요한가&#34;&gt;1. 서론: 인덱스는 왜 중요한가?&lt;/h2&gt;
&lt;p&gt;데이터베이스의 성능은 곧 서비스의 응답 속도와 직결됩니다. 데이터가 수만 건일 때는 문제가 없다가, 수백만 건을 넘어서는 순간 웹 사이트가 느려지는 경험을 해보셨을 겁니다. 이때 가장 먼저 확인해야 할 것이 바로 **인덱스(Index)**입니다.&lt;/p&gt;
&lt;p&gt;인덱스는 책의 맨 뒤에 있는 &amp;lsquo;색인&amp;rsquo;과 같습니다. 방대한 데이터 속에서 내가 원하는 정보를 찾기 위해 처음부터 끝까지 다 뒤지는 &amp;lsquo;Full Table Scan&amp;rsquo;을 방지하고, B-Tree 구조를 통해 원하는 위치로 즉시 점프하게 해줍니다.&lt;/p&gt;
&lt;h2 id=&#34;2-실무-사례-500만-건의-주문-테이블-쿼리-최적화&#34;&gt;2. 실무 사례: 500만 건의 주문 테이블 쿼리 최적화&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;상황:&lt;/strong&gt; 쇼핑몰 프로젝트에서 특정 사용자의 최근 주문 내역을 조회하는 쿼리가 5초 이상 소요되고 있습니다.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="1-서론-인덱스는-왜-중요한가">1. 서론: 인덱스는 왜 중요한가?</h2>
<p>데이터베이스의 성능은 곧 서비스의 응답 속도와 직결됩니다. 데이터가 수만 건일 때는 문제가 없다가, 수백만 건을 넘어서는 순간 웹 사이트가 느려지는 경험을 해보셨을 겁니다. 이때 가장 먼저 확인해야 할 것이 바로 **인덱스(Index)**입니다.</p>
<p>인덱스는 책의 맨 뒤에 있는 &lsquo;색인&rsquo;과 같습니다. 방대한 데이터 속에서 내가 원하는 정보를 찾기 위해 처음부터 끝까지 다 뒤지는 &lsquo;Full Table Scan&rsquo;을 방지하고, B-Tree 구조를 통해 원하는 위치로 즉시 점프하게 해줍니다.</p>
<h2 id="2-실무-사례-500만-건의-주문-테이블-쿼리-최적화">2. 실무 사례: 500만 건의 주문 테이블 쿼리 최적화</h2>
<p><strong>상황:</strong> 쇼핑몰 프로젝트에서 특정 사용자의 최근 주문 내역을 조회하는 쿼리가 5초 이상 소요되고 있습니다.</p>
<p><strong>기존 쿼리:</strong></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">SELECT</span><span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">*</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">FROM</span><span style="color:#6e7681"> </span>orders<span style="color:#6e7681"> 
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">WHERE</span><span style="color:#6e7681"> </span>user_id<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">12345</span><span style="color:#6e7681"> 
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">ORDER</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">BY</span><span style="color:#6e7681"> </span>created_at<span style="color:#6e7681"> </span><span style="color:#ff7b72">DESC</span><span style="color:#6e7681"> 
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">LIMIT</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">10</span>;<span style="color:#6e7681">
</span></span></span></code></pre></div><p><strong>문제점:</strong> <code>user_id</code>에 인덱스가 없다면, MySQL은 500만 건의 데이터를 모두 확인해야 합니다.</p>
<h3 id="해결책-복합-인덱스composite-index-생성">해결책: 복합 인덱스(Composite Index) 생성</h3>
<p>단순히 <code>user_id</code>에만 인덱스를 거는 것이 아니라, 정렬 조건까지 포함한 복합 인덱스를 생성하여 성능을 극대화합니다.</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;font-weight:bold">#</span><span style="color:#6e7681"> </span><span style="color:#f85149">최적의</span><span style="color:#6e7681"> </span><span style="color:#f85149">인덱스</span><span style="color:#6e7681"> </span><span style="color:#f85149">생성</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">CREATE</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">INDEX</span><span style="color:#6e7681"> </span>idx_user_id_created_at<span style="color:#6e7681"> </span><span style="color:#ff7b72">ON</span><span style="color:#6e7681"> </span>orders<span style="color:#6e7681"> </span>(user_id,<span style="color:#6e7681"> </span>created_at<span style="color:#6e7681"> </span><span style="color:#ff7b72">DESC</span>);<span style="color:#6e7681">
</span></span></span></code></pre></div><p>이 설정을 통해 MySQL은 특정 사용자의 데이터를 찾자마자 이미 정렬된 상태로 데이터를 읽어오기 때문에, 5초 걸리던 쿼리가 0.01초 내외로 단축됩니다.</p>
<h2 id="3-인덱스-설계-시-반드시-지켜야-할-원칙">3. 인덱스 설계 시 반드시 지켜야 할 원칙</h2>
<ol>
<li><strong>카디널리티(Cardinality)가 높은 컬럼 선택:</strong> 성별(남/여)처럼 중복도가 높은 컬럼보다는 주민번호나 이메일처럼 중복도가 낮은 컬럼에 인덱스를 걸어야 효과적입니다.</li>
<li><strong>WHERE 절뿐만 아니라 ORDER BY, GROUP BY도 고려:</strong> 쿼리 실행 계획(Explain)을 확인하여 인덱스가 정렬 과정에서도 사용되는지 확인해야 합니다.</li>
<li><strong>인덱스 과유불급:</strong> 인덱스는 조회 속도를 높여주지만, INSERT, UPDATE, DELETE 시에는 인덱스도 함께 갱신해야 하므로 쓰기 성능을 저하시킵니다. 꼭 필요한 곳에만 생성하세요.</li>
</ol>
<h2 id="4-인덱스가-작동하지-않는-나쁜-쿼리-예시">4. 인덱스가 작동하지 않는 나쁜 쿼리 예시</h2>
<p>인덱스를 만들어 놓고도 제대로 활용하지 못하는 경우입니다:</p>
<ul>
<li><strong>컬럼을 가공하는 경우:</strong> <code>WHERE ABS(score) &gt; 100</code> (인덱스 사용 불가) -&gt; <code>WHERE score &gt; 100 OR score &lt; -100</code>으로 변경.</li>
<li><strong>부정형 조건을 사용하는 경우:</strong> <code>WHERE status != 'DELETED'</code> (인덱스 효율이 매우 떨어짐).</li>
<li><strong>LIKE 연산자 앞에 %를 붙이는 경우:</strong> <code>WHERE name LIKE '%찬열'</code> (Full Scan 유발).</li>
</ul>
<h2 id="5-마치며-explain을-습관화하자">5. 마치며: EXPLAIN을 습관화하자</h2>
<p>내가 만든 인덱스가 실제로 잘 작동하는지 확인하는 가장 좋은 방법은 쿼리 앞에 <code>EXPLAIN</code> 키워드를 붙여 실행 계획을 분석하는 것입니다. <code>type</code> 항목이 <code>ref</code>나 <code>range</code>가 아닌 <code>ALL</code>로 나온다면 즉시 개선이 필요합니다.</p>
<p>데이터가 쌓이기 전에 미리 인덱스 전략을 수립하여, 사용자에게 쾌적한 환경을 제공하는 개발자가 됩시다.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
