강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

parkhs님의 프로필 이미지
parkhs

작성한 질문수

스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판

댓글 무한 depth - 테이블&구현 설계

두 쿼리문의 차이

해결된 질문

작성

·

141

0

안녕하세요, 쿠케님 강의 만족스럽게 수강하고 있는 수강생입니다.

아래 2개의 쿼리문에 대해 첫번째 쿼리문에 where article_id = 1 이라는 조건문이 있고(비록 index를 생성한 컬럼이지만), 두번째 쿼리문에서는 where article_id가 빠진 상태인데도 첫번째 쿼리문의 속도가 더 빨랐습니다.

 

explain 해보니,

두번째 쿼리문에 Using filesort가 존재하는데,

order by path로 인해 저희가 지정한 index의 컬럼인데도 불구하고 왜 Using filesort가 되고, 속도가 첫번째 쿼리문에 비해 조건이 없는데도 더 느린지 잘 이해가 안됩니다.

 

image.png
mysql> explain select path from comment_v2 where article_id = 1 order by path desc limit 10;
+----+-------------+------------+------------+------+---------------------+---------------------+---------+-------+---------+----------+----------------------------------+
| id | select_type | table      | partitions | type | possible_keys       | key                 | key_len | ref   | rows    | filtered | Extra                            |
+----+-------------+------------+------------+------+---------------------+---------------------+---------+-------+---------+----------+----------------------------------+
|  1 | SIMPLE      | comment_v2 | NULL       | ref  | idx_article_id_path | idx_article_id_path | 8       | const | 4990965 |   100.00 | Backward index scan; Using index |
+----+-------------+------------+------------+------+---------------------+---------------------+---------+-------+---------+----------+----------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select path from comment_v2 order by path desc limit 10;
+----+-------------+------------+------------+-------+---------------+---------------------+---------+------+---------+----------+-----------------------------+
| id | select_type | table      | partitions | type  | possible_keys | key                 | key_len | ref  | rows    | filtered | Extra                       |
+----+-------------+------------+------------+-------+---------------+---------------------+---------+------+---------+----------+-----------------------------+
|  1 | SIMPLE      | comment_v2 | NULL       | index | NULL          | idx_article_id_path | 110     | NULL | 9981930 |   100.00 | Using index; Using filesort |
+----+-------------+------------+------------+-------+---------------+---------------------+---------+------+---------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)

답변 2

1

쿠케님의 프로필 이미지
쿠케
지식공유자

parkhs님, 안녕하세요!

일단 강의 잘 수강해주셔서 감사하고 뿌듯하네요~!

 

문의 주신 내용 답변 드립니다!

강의에서는 인덱스를 article_id asc, path asc로 만든 상황인데요,

1번 게시글과 2번 게시글에서 각각 3개의 댓글이 있다고 가정해보겠습니다.

그러면 다음과 같이 정렬된 인덱스 데이터가 생기게 됩니다.

article_id | path
1          | 00000
1          | 00001
1          | 00002
2          | 00000
2          | 00001
2          | 00002

B+ Tree 자료구조로 만들어지는 인덱스 데이터는 위처럼 정렬되어 있을 것입니다.

트리의 리프 노드에 위 순서로 정렬되어 있는 형태를 생각해주시면 됩니다.

article_id 오름차순, article_id가 동일할 때에는 path 오름차순으로 정렬된 것입니다.

 

article_id = 1 order by path desc 쿼리를 수행해보겠습니다.

article_id가 동일할 때에는 path로 2차 정렬되어 있으므로,

(article_id=1, path=00002)의 위치를 로그 시간(O(logN))에 즉시 찾을 수 있습니다.

트리의 탐색은 로그 시간에 수행되므로, 아주 빠르게 수행되는 것입니다.

해당 위치에서부터 backward scan(역순 스캔)으로 limit M개의 데이터를 추출하면 되겠죠?

조회 시점에 따로 정렬할 필요 없이, 이미 정렬된 인덱스에서 기준점을 찾고 스캔만 하면 충분했습니다.

정렬된 인덱스 데이터가 조회 조건을 만족할 수 있었기 때문입니다.

 

다음으로 order by path desc 조건을 보겠습니다.

article_id = 1 조건은 사라졌으니, path로 정렬된 데이터를 찾아야합니다.

그런데 인덱스는 article_id가 동일할 때에 path로 정렬되어 있는 것이므로,

path로만 정렬하려면 조회 시점에 데이터를 다시 정렬해야 됩니다.

article_id | path
1          | 00002
2          | 00002
1          | 00001
2          | 00001
1          | 00000
2          | 00000

path 내림차순 정렬하면, 위처럼 데이터가 다시 만들어져야겠죠?

정렬된 인덱스만으로는 path 정렬 조건을 만족하지 못하므로,

조회 시점에 전체 데이터를 다시 정렬해야 하는 과정이 당연히 필요합니다.

그래서 filesort가 수행된 것이라고 봐주시면 됩니다!

 

쿼리에 조건이 많고/적음보단, 인덱스를 효율적으로 타도록 최적화 할 수 있는지가 성능에 중요한 요소가 됩니다.

인덱스 순서가 중요하다는 것도 이러한 맥락 중 하나로 봐주시면 되네요.

전자의 경우, 조건에 의해 별도 정렬 없이 인덱스 데이터를 즉시 스캔할 수 있었던 반면,

후자의 경우, 인덱스 데이터와 정렬 조건이 다르기 때문에 조회 시점에 재정렬이 필요했습니다.

 

게시글 강의에서 인덱스가 만들어지는 원리에 대해서 설명하므로 복습도 해보시고,

아직 B+ Tree 구조가 낯설다면 별도로 추가 학습해 보셔도 좋을 것 같네요!

 

혹시 더 궁금한 점 있으시면 편히 문의 주세요!

parkhs님의 프로필 이미지
parkhs
질문자

이해하기 쉽게 설명해주셔서 감사합니다~!

0

안녕하세요, 인프런 AI 인턴입니다. parkhs님.

MySQL의 EXPLAIN 결과를 통해 두 쿼리의 실행 차이와 성능 관련 차이를 설명드리겠습니다.

두 쿼리에서 큰 차이는 WHERE 절의 존재여부입니다. 첫 번째 쿼리는 WHERE article_id = 1 조건을 사용하고, 두 번째 쿼리는 조건이 없습니다. 이 차이가 인덱스 사용 방식과 정렬 필요성에 영향을 줍니다.

첫 번째 쿼리

SELECT path FROM comment_v2 WHERE article_id = 1 ORDER BY path DESC LIMIT 10;

이 쿼리는 WHERE 조건이 존재하며, 인덱스 idx_article_id_path를 사용하여 article_id에 대한 필터링을 수행합니다. 이는 효율적인 범위 스캔을 가능하게 하여 데이터의 위치를 빠르게 찾아 정렬을 최소화합니다. Backward index scan; Using index을 보시면, 인덱스를 사용하여 조건에 맞는 데이터를 불러오고, 역방향으로 데이터를 읽어들여 정렬에 대한 추가적 비용을 줄입니다.

두 번째 쿼리

SELECT path FROM comment_v2 ORDER BY path DESC LIMIT 10;

이 쿼리는 특정한 WHERE 조건이 없기 때문에, MySQL은 테이블의 모든 레코드를 스캔하여 ORDER BY path DESC 절에 의해 정렬해야 합니다. 이때 “Using filesort”가 나타납니다. filesort는 MySQL이 메모리 상에 모든 데이터를 읽어 정렬하는 추가 작업을 해야 한다는 것을 의미하며, 이는 연산 비용이 높아져 쿼리가 느려지는 원인이 됩니다.

Using filesort의 영향

Using filesort는 인덱스만으로 정렬이 충분하지 않은 경우 발생하며, 모든 데이터를 가져와 메모리에서 정렬하는 과정을 포함하기 때문에, 대량의 데이터가 있는 테이블에서는 성능 저하를 유발할 수 있습니다.

결론

WHERE 조건이 쿼리 성능에 큰 영향을 미치는 중요한 이유 중 하나는 필터링 과정을 통해 효과적으로 데이터 양을 줄이고, 인덱스 활용도를 높이기 때문입니다. 그래서 조건이 포함된 첫 번째 쿼리가 두 번째 쿼리보다 성능이 더 좋게 나타납니다.

이해를 돕고자 인프런 커뮤니티의 관련 질문을 참고해 보세요:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

parkhs님의 프로필 이미지
parkhs

작성한 질문수

질문하기