Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[조회 성능 개선하기] 검프(김태정) 미션 제출합니다. #6

Merged
merged 5 commits into from
Nov 1, 2021

Conversation

Livenow14
Copy link

안녕하세요 웨지 ㅎㅎㅎ 검프입니다!
페어 꼭 하고싶었는데, 리뷰이, 리뷰어로 만나네요!! 반갑습니다 :)
편하게 보실려면 조회 성능 개선하기 여기서 볼 수 있습니다!
미션을 진행하며 질문사항이 생겼어요 먼저 질문사항 적을게요.

PR 질문사항.

A. 쿼리 연습

CREATE INDEX `idx_부서_비고_부서번호`  ON `tuning`.`부서` (비고, 부서번호);

부서 테이블에 이러한 인덱스를 걸었을때 아래와 같은 실행계획이 나오는데요,

https://user-images.githubusercontent.com/48986787/136785605-de541c25-dd16-47cc-aa82-6baa84cae07e.png

부서 관리자의 rows가 24개가 불러와 지는 것을 알 수 있어요.

전반적인 filtered를 고려했을 때, 위와 같이 걸어도 괜찮다고 생각을 했었는데,

인덱스를 걸지 않았을 때는

https://user-images.githubusercontent.com/48986787/136788504-25004d7e-0a27-4995-8e9a-691ebbfc8e2f.png

부서의 extra가 Using where, Using tempoarary, Using filesort로 바뀌어요. filter의 퍼센트도 11퍼로 대폭 줄었네요.
다만 rows를 9개만 가져오기 때문에, rows의 최적화가 이뤄지지 않나 싶어요.

위와 같은 상황에선, 어떠한 것을 기준으로 index를 둘지 말지 결정해야 할까요? (현재 실행 속도는 동일합니다.)

B. 인덱스 설계

boolean을 인덱싱해야하나? 라는 질문의 답에, 저는 일단 Boolean은 카디널리티가 낮아, 설정하지 않는다 라고 결정했어요. 하지만 Count 쿼리에서 성능향상을 위해서는 Unique 제약조건과 indexing을 해줘야하기에,
primary인 id와 boolean 컬럼을 복합 Unique 키로 걸었어요.

이렇게 COUNT 쿼리의 최적화가 필요한 경우, 카디널리티가 낮은 컬럼의 인덱스를 고려할때,
어떤 기준으로 둬야할까요? 웨지의 생각이 궁금해요!

결론적으로

JOIN문을 작성하는법, Index를 제대로 쓰는 방법을 미션을 진행하며 점차 체득화 된거 같아요. 그래서 초반에 어색한? 쿼리들이 있는데, 이부분들은 웨지의 폭풍 피드백을 받으며 수정하고 싶어서 남겨놨어요 😊

이번 피드백 잘 부탁드립니다!! 🙇🏻‍♂️

@sihyung92
Copy link

1. 위와 같은 상황에선, 어떠한 것을 기준으로 index를 둘지 말지 결정해야 할까요? (현재 실행 속도는 동일합니다.)
인덱스는 조회속도 개선을 위한 방법입니다. 대신 하드디스크의 용량과 삽입/수정/삭제 속도를 희생합니다. 타겟으로 잡은 쿼리의 조회속도가 동일하다고 하셨죠? 그렇다면 성능개선 효과가 없는 쿼리최적화를 위해 인덱스를 추가하는 건 맞지 않다고 생각합니다. 개인적으로 성능최적화에서 볼건, 쿼리코스트도, 실행계획도 아닌 쿼리수행속도 가 비즈니스 목표에 미치는가 못 미치는가가 가장 중요하다고 생각합니다.

그리고 성능최적화가 되지 않은 이유는 24row밖에 안 되는 테이블이라, 풀테이블스캔과 인덱스 스캔간의 성능차이가 무의미한 수준이기 때문이라고 봅니다.

2. 이렇게 COUNT 쿼리의 최적화가 필요한 경우, 카디널리티가 낮은 컬럼의 인덱스를 고려할때,
어떤 기준으로 둬야할까요?

선택도가 0.5인 hobby 칼럼 얘기하시는 거겠죠? 보통 인덱스 설계를 할 때 카디널리티가 낮을 수록 인덱싱 효과가 뛰어나다고 하기 때문에, 복합칼럼으로 구성하신건 옳은 선택같습니다. 하지만 COUNT쿼리만 놓고 생각해 봤을 때, (boolean)과 (boolean, id)의 차이는 없을 것 같네요. 둘다 인덱스 풀 스캔을 하겠죠.

@sihyung92
Copy link

미션 제출부에선 흠잡을 곳이 없어보입니다.
다만 B 미션에서
hospital name 타입 VARCHAR(255)로 변경, name Unique 제약조건 설정
해 준 부분이 걸리네요. 병원 이름이 255자 이하일 것을 확신할 수 있나요?
궁금해서 찾아봤는데 제일 긴 병원이름은 '학교법인 고려중앙학원 고려대학교 의과대학 부속병원' 라고 하네요 생각보다 짧네요 ㅎ ㅈㅅ

unique에 대해선 사랑의병원 라는 동일 이름을 가진 병원이 많습니다. unique 설정은 나중에 오류를 일으킬 소지가 있는 것 같네요. 저도 text타입에 인덱싱을 할 수 없기 때문에, 데이터 타입 변경을 고려해봤는데, 병원 테이블에 대한 인덱싱이 없어도 제가 원하는 성능 목표치를 달성하기엔 충분 했기에 그대로 두었습니다. 비즈니스적인 의미가 변하지 않았는데, 인덱싱을 위한 데이터 타입 변경은 꺼림칙해서요, 검프는 어떻게 생각하시나요?

Copy link

@sihyung92 sihyung92 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리드미 보기가 정말 편했어요! 검선생 다운 멋진 정리네요~~ 수고하셨습니다!

전 이번에 정말 많이 배우고 느꼈는데, 검프도 마찬가지겠죠? ㅎ_ㅎ
코멘트로 질문에 대한 대답과 미션에 대한 리뷰 남겼습니다~~ 확인해주세요~!

@Livenow14
Copy link
Author

Livenow14 commented Oct 13, 2021

안녕하세요 웨지!! 두 번째 PR이네요.
우선 수정한 사항에 대해 설명할게요.

수정사항 - 쿼리 개선

애매하게 요구사항을 만족하는 (0.9/sec)쿼리를 개선했어요. 대체로 인덱스, 유니크 설정을 잘못해서 생기는 레이턴시였어요.
또한, 쿼리들을 보기 좋게 수정했어요.

리뷰시 참고

아직 리뷰 과정이기에, 결과 자체가 변경된 부분에 대해서는 - 표시를 했어요.
"문제해결" 부분에 문제상황과, 해결을 어떻게 했는지 정리했어요.
이후 Merge 전, 처음 문서대로 수정할 예정입니다 😁

비즈니스적인 의미가 변하지 않았는데, 인덱싱을 위한 데이터 타입 변경은 꺼림칙해서요, 검프는 어떻게 생각하시나요?

TEXT가 65,535 byte까지 지원을 한다고 합니다. 병원 이름이 암호화가 되지 않는 이상 이정도까지의 데이터가 들어오지 않을 것이라 생각했어요. 그래서, 타입을 변경해도 좋지 않을까? 생각했어요. 마침 인덱싱을 하려 했었고요!! ㅎㅎ
하지만 웨지의 말씀처럼, 비즈니스 의미가 변하지 않았는데, 단편적인 판단하에 변경하는 것이 아니라 생각했고, 또 쿼리를 최적화하는 과정에서 name의 인덱싱이 불필요하다 느꼈기에, 다시 원래대로 원복했어요
좋은 답변 감사합니다!! ☺️

질문했던 부분들에 대한 피드백을 확인했어요!
정말 좋은 답변들이 많아 많이 배웠어요. 많은 인사이트를 얻어 갑니다 역시 웨지 😊
이번에도 많은 피드백 부탁드립니다 🙇🏻‍♂️

@sihyung92
Copy link

^^ 딱히 피드백 할 게 없네요
적용한 내용 잘 봤습니다! 노력과 고민이 많이 보이는 내용이라 좋았습니다.

이것저것 인덱스를 잡다 느낀 것이 인덱스 칼럼의 분포도 또한 중요하구나 하는 내용이었습니다.
마지막 5번, 서울대병원에 다닌 30대 환자들을 운동 횟수 별로 집계하는 내용을 하다가,

programmer의 member_id라는 칼럼이 있습니다. 선택도가 0.3정도 되는 칼럼이 있습니다.(33만 건 중 유니크 값이 10만건여)
그런데 하나의 member_id가 22만건이고, 나머지 로우들은 유니크한 칼럼이었습니다. (이 정도면 장부조작이라 경찰에 신고해야됩니다)

반면에 선택도가 0.01(32건)정도 되는 칼럼이 있습니다. hospital_id로, 각 건이 1000~10000건 row 사이로 분포가 어느정도 균일합니다.

인덱스는 카디널리티가 높은 걸로 잡아야 한다는 인식 덕분에 member_id로 잡아봤지만, 분포도가 균일한 hospital_id 인덱스보다 성능이 훨씬 떨어지는 현상을 확인했습니다.

인덱스라는 것이 PK와 맵핑되는 세컨더리 테이블이므로(INNO DB 한정이지만), 분포도가 지나치게 편중된 칼럼은 세컨더리 테이블 내에서 검색시에 B-TREE의 검색효율 성능을 충분히 낼 수 없기 때문이라고 생각합니다 ^_^

approve 하겠습니다! 수고했어요~~

Copy link

@sihyung92 sihyung92 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여윽시 검선생이다
어프로브

@Livenow14
Copy link
Author

안녕하세요 웨지!! (거의 마지막일듯한) PR입니다. ㅎㅎ

수정사항 - 쿼리 개선

"서울대병원에 다닌 20대 India 환자들을 병원에 머문 기간별로 집계하세요. (covid.Stay)"에 제약조건이 제대로 잡혀있지 않아 수정했어요.
또한, 인덱싱이 제대로 걸려 있지 않은 곳을 전부 제거후, 다시 설정했어요 ㅎㅎ. 지금와서 보니, 제대로 걸려있지 않는 곳이 많더라구요 :)

수정사항 - 리드미 수정

수정사항들을 제거 후, 처음 PR을 날렸을때와 같은 구조로 수정했어요.
미션을 진행하며 생기는 의문점들은 "참고사항" 에 정리했습니다!

피드백에 웨지의 생각들을 말씀해주셔서 좋았어요!!
덕분에 많이 배워갑니다..! 수고하셨어요 🙇🏻‍♂️

@sihyung92
Copy link

sihyung92 commented Oct 16, 2021

어프로브 한 상태라.. 추가적으로 알게 된 사항들 공유할게요

INNO_DB는 GROUP BY 칼럼에 대해 정렬을 하고, ORDER BY NULL 키워드로 해당 파일 솔트를 제거할 수 있단건 알고 계셨네요. MYSQL만의 특징이므로, 다른 DBMS엔 해당 안한다는 점도 알아두시면 좋을 것 같아요
image

또 복합인덱스는 단일인덱스에 비해 조회성능이 느립니다. 인덱스 끼리의 카디널리티 곱만큼의 세컨더리 테이블이 생성될 걸 생각해보면, 단일 인덱스를 이용할 때 보다 느리겠죠? 씨유 성능강의에서 복합인덱스와 단일인덱스 끼리의 중복내용에 대해 삭제하라고 한 내용은,
image
INSERT 상황에서 중복인덱스 때문에 성능에 악영향을 주기 때문에 삭제하라고 한 것입니다.

복합인덱스 구성시의 선두칼럼은 중복도가 낮은, 카디널리티가 높은 칼럼을 잡는 것이 일반적입니다. 하지만 해당 예제에선 programmer 테이블에서 한 멤버ID가 60%이상의 로우에서 중복되기 때문에 반대의 결과가 나타났다 생각합니다. 사실상 카디널리티가 2 수준에 불과한 것이, 32개 로우로 준수한 분포도를 보여주는 hospital_id 보다 조회성능이 느렸다고 예상되네요. 쿼리성능은 이처럼 관여하는 요소가 많은 복잡계라 어려우면서도, 재미있는 요소인 것 같습니다 ^^ 특정 인덱스를 잡았다고 안심하지 않고 항상 성능을 확인해보는 습관이 중요하다고 생각해요.

검검짱짱

@Livenow14 Livenow14 self-assigned this Nov 1, 2021
Copy link

@sihyung92 sihyung92 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

검짱왕킹프킹짱왕 리뷰를 완료할 땐 머지가 안 되어서 잊고 있었네요! 뒤늦은 머지 선물~~ 얼마 남지 않은 우테코 기간 같이 화이팅해부자~~!

@sihyung92 sihyung92 merged commit 76cabc7 into woowacourse:livenow14 Nov 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants