
mysql 공식문서에 기재된 Covering Index의 정의는 다음과 같습니다.
An index that includes all the columns retrieved by a query. Instead of using the index values as pointers to find the full table rows, the query returns values from the index structure, saving disk I/O.
쿼리에 사용된 모든 컬럼을 다 가지고 있는 인덱스를 Covering Index라고 합니다. 이는 단순히 WHERE절에 사용되는 컬럼만을 의미하는 게 아니라 SELECT절, ORDER BY절, GROUP BY절 등에 사용된 모든 컬럼을 의미합니다.인덱스에 있는 데이터 자체를 반환합니다. 페이지 블록에 접근해 데이터를 가져오지 않기 때문에 디스크 I/O비용을 절약할 수 있습니다.Extra 컬럼에 'Using index'값이 적혀있다면 이는 Covering Index로 실행된다는 의미입니다.

cf) Extra 컬럼에 'Using index'가 없고 단순히 type 컬럼만 index라면 이는 index full scan으로 실행된다는 의미입니다. index full scan은 인덱스 테이블을 모두 탐색한다는 의미로 table full scan보다는 속도가 빠르지만 전체적으로 봤을 때 빠른 동작방법은 아닙니다.
CREATE TABLE test (
id int NOT NULL AUTO_INCREMENT,
col1 int,
col2 int,
col3 varchar(255),
col4 varchar(255),
PRIMARY KEY (id),
KEY ix1 (col1,col2,col3)
);
EXPLAIN SELECT col1 FROM test WHERE col2 > 10;

EXPLAIN SELECT col1, col4 FROM test WHERE col2 > 10;

EXPLAIN SELECT id, col1 FROM test WHERE col2 > 10;

인덱스 테이블의 데이터들이 왼쪽 컬럼을 기준으로 정렬되어 있기 때문에 column의 순서가 중요합니다.
| col1 | col2 | col3 |
|---|---|---|
| 1 | 1 | 3 |
| 1 | 1 | 4 |
| 1 | 2 | 1 |
| 1 | 2 | 2 |
| 2 | 1 | 1 |
| 2 | 1 | 1 |
| 2 | 2 | 1 |
| 2 | 2 | 2 |
[ORDER BY | GROUP BY] col2;
[ORDER BY | GROUP BY] col1, col3;
[ORDER BY | GROUP BY] col2, col3, col1;
[ORDER BY | GROUP BY] col2, col3 DESC, col1;
[ORDER BY | GROUP BY] col1, col2, col3, col4;
[ORDER BY | GROUP BY] col1;
[ORDER BY | GROUP BY] col1, col2;
[ORDER BY | GROUP BY] col1, col2, col3;
WHERE col1 = '' [ORDER BY | GROUP BY] col2;
WHERE col1 = '' AND col2 = '' [ORDER BY | GROUP BY] col3;
EXPLAIN SELECT *
FROM test
ORDER BY col1;

이때 아래와 같이 쿼리를 수정하면 Covering Index를 활용해 동일한 결과를 얻을 수 있습니다.
SELECT *
FROM (
SELECT id
FROM test
ORDER BY col1
) b INNER JOIN test a ON a.id = b.id;
