묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
Spring Boot 프로젝트에 Redis 셋팅 추가하기에서 13분 질문있습니다.
Spring Boot 프로젝트에 Redis 셋팅 추가하기에서 13분에서요.스프링부트 종료하고 다시 사작한 화면에서 cmd에서 cash * 누르면 캐시가 없던데 캐시는 휘발성인가요?
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
풀 인덱스 스캔 질문있습니다.
CREATE INDEX idx_name ON users (name); EXPLAIN SELECT * FROM users ORDER BY name LIMIT 10; <- 이 부분에서 idx_name을 안쓰고 컬럼명만 작성했는데 어떻게 풀 인덱스 스캔을 썼는지 아는건가요?
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
멀티컬럼인덱스 질문있습니다.
강의자료:https://jscode.notion.site/661a5bcd11c74b4c97520460dbc4a328주의 사항 2에서요. 정렬을 자세히 잘 살펴보면 이름 기준으로 정렬이 되어 있지는 않다. 왜냐면 같은 부서를 가진 데이터끼리만 정렬을 시켰기 때문이다. 실제로 아래 SQL문을 실행시킬 때 인덱스를 활용하지 못한다.윗 부분에 말 뜻이. 처음부터 이름 순으로 정렬이 안되어있어서 멀티컬럼인덱스가 사용이 어렵다는 말씀인가요?즉 아래 컬럼 처럼 안되어 있어서 멀티 컬럼인덱스가 적용이 안된다는 말씀인가요?부서 | 이름 | 순위----------------------회계 | 김미현 | 2 회계 | 김민재 | 3 인사 | 하재원 | 6 운영 | 이재현 | 4 운영 | 조민규 | 5 인사 | 최지우 | 7 회계 | 박미나 | 1
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
레디스 환경 셋팅 질문있습니다.
선생님 코드 복붙했는데 어느 부분이 틀린지 잘 모르겠습니다.class RedisCacheConfig 부분에서 RedisConnectionFactory redisConnectionFactory 이 부분이 에러가 나고class BoardService애서 cacheManager = "boardCacheManager" 여기서도 에러가 납니다.파일 첨부합니다.
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
엘라스틱 서치와 레디스의 차이점을 알고 싶습니다.
엘라스틱 서치와 레디스의 차이점을 알고 싶습니다. 그리고 강의 중에 엘라스틱 서치도 redis-cli로 접속하여 값을 볼수있는데. 이것은 왜 redis-cli 를 사용하는지도 알고 싶습니다.
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
-parameters
http://localhost:8080/boards 로 접근시 해당 에러가 발생합니다
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
쿼리 튜닝 관련 질문 (limit)
안녕하세요 강사님 좋은 강의 정말 감사드립니다. 실습 따라면서 튜닝을 익혀가고있는데 이번 강의에서 이해되지 않는 부분이 있어 질문 남깁니다.일단 저는 MariaDB를 이용하여 실습을 하고 있습니다 죄송합니다 ㅠ -- 튜닝 전 쿼리 SELECT st.student_id, st.name, AVG(sc.score) AS average_score FROM students st JOIN scores sc ON st.student_id = sc.student_id GROUP BY st.student_id, st.name, sc.year, sc.semester HAVING AVG(sc.score)=100 AND sc.year=2024 AND sc.semester=1; -- 튜닝 쿼리 SELECT st.student_id, st.name, AVG(sc.score) AS average_score FROM students st JOIN scores sc ON st.student_id = sc.student_id WHERE sc.year=2024 AND sc.semester=1 GROUP BY st.student_id, st.name, sc.year, sc.semester HAVING AVG(sc.score)=100;두 쿼리 실행 속도에 별로 차이가 없어서 1) students, scores 두 테이블 각각 데이터 300만개로 늘리고 2) 두 쿼리 모두 동일하게 limit 10을 붙여줬더니 갑자기 성능 차이가 엄청나게 났습니다. -- 튜닝 전 쿼리 SELECT st.student_id, st.name, AVG(sc.score) AS average_score FROM students st JOIN scores sc ON st.student_id = sc.student_id GROUP BY st.student_id, st.name, sc.year, sc.semester HAVING AVG(sc.score)=100 AND sc.year=2024 AND sc.semester=1 LIMIT 10; -- 튜닝 쿼리 SELECT st.student_id, st.name, AVG(sc.score) AS average_score FROM students st JOIN scores sc ON st.student_id = sc.student_id WHERE sc.year=2024 AND sc.semester=1 GROUP BY st.student_id, st.name, sc.year, sc.semester HAVING AVG(sc.score)=100 limit 10;제가 궁금한 것은 limit 10을 붙이면 튜닝을 하든 안하든 실행 속도가 더 줄어들어야 할 것 같은데 튜닝 전 쿼리가 갑자기 1분넘게 소요되더라고요.튜닝 후 쿼리는 limit을 붙이나 안붙이나 별 차이가 없는데 튜닝 전 쿼리는 왜 limit을 붙이면 갑자기 성능이 엄청나게 저하되는걸까요..?? 확인해주시고 답변 주시면 많은 도움 될 것 같습니다 감사합니다!
-
해결됨비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
페이지기반 페이지네이션 쿼리를 최적화하고 싶습니다.
게시판 비슷한 기능을 구현중인데 아무래도 커서기반보다는 페이지를 원하는대로 넘나들 수 있는 페이지기반 페이지네이션을 구현하고 싶어서 구현은 했는데 대용량 데이터에는 맞지 않은 듯해서 어떻게 최적화를 하면 좋을지 고민하고 있습니다.현재 저는 Postgres DB를 사용하고 있으며SQL를 전부 올리기보다 고민하고 있는 부분에 대해서만 간략히 적도록 하겠습니다.api에서는 SQL를 연속으로 두번 실행시키고 있습니다.1. 조건에 맞는 모든 ROW를 COUNT2. 1페이지당 사이즈와 현재 페이지로 OFFCET FETCH NEXT ROWS ONLY 절을 사용해서 ROW를 건너뛰고 검색을 하고 있는데지금 구현대로면 최악의 경우일때는 거의 DB 전체를 두번 조회하는거나 다름 없을 것 같습니다.사이드 프로젝트일때는 상관없을 것 같긴한데 실무에서는 어떤방식으로 최적화가 가능할까요?검색을 해보니 대용량 데이터에서는 커서기반으로 하라는 의견이 많은 것 같은데 그래도 페이지기반의 장점을 살리고 싶습니다.
-
미해결Real MySQL 시즌 1 - Part 1
GAP 락에 대한 질문 드립니닷..!
해당 강의와 직접적으로 연관있지는 않으나, Lock 관련하여 공부하던 중 성욱님의 MySQL GAP Lock (두번째 이야기) 글을 보게 되었습니다.우선 정말 많은 도움이 되었음에 감사드리며, 해당 글 관련하여 질문을 드리고 싶습니다. (SELECT FOR UPDATE와도 관련있는 내용이라, 이곳 게시판을 통해 질문 드립니다.)위 글의'왜 supremum 레코드를 잠그나요 ?' 단락에서, 8, 9 번째 과정을 보면 다음과 같습니다.8. 다음 페이지에서 id=137 보다 큰 (첫번째) 레코드인 id=138 읽기9. WHERE 조건에 일치하지 않으므로 잠금 걸지 않음그런데 그 아래에서 다음과 같은 내용을 말씀해 주십니다.'REPEATABLE-READ 격리 수준을 사용하는 MySQL 서버에서는 검색하고 스캔했던 인덱스 레코드를 잠근다는 아주 기본적인 규칙 때문에 잠금이 발생하고 있었던 것이죠. 사용자 데이터가 아닌 시스템 레코드(supremum)까지도 말이죠.'그러나 이 설명에 따르면, '왜 supremum 레코드를 잠그나요 ?' 에서 언급한 동작에 모순이 발생하는 것 같습니다.5,6,7 번 과정에서는 supremum record를 읽었기에 잠갔음에도 불구하고,8, 9번의 과정에서는 id=138 읽었지만 잠그지 않고 종료했기 때문입니다.위 내용이 모순된 것이라 가정하고,왜 supremum record에 Lock이 걸리도록 동작했는지에 대한 이유를 개인적으로 찾아보고 공부한 내용들에 기반하여 추측해 보았습니다. (아직 내용을 완벽히 공부하지 못해 틀린 내용이 있을 수 있습니다. 혹시 틀린 부분이 있다면 지적해주시면 감사하겠습니다!)MySQL 의 공식 문서의 내용에 따르면, Gap Lock은 Gap Lock 의 기준이 되는 index record 이전의 간격을 잠급니다.A next-key lock on an index record also affects the “gap” before that index record- MySQL 공식문서 - Next Key Lock그러나 Gap락이 특정 index record 이전의 간격을 잠근다는 위 설명에 따르면, 어떤 index의 가장 마지막 record 이후의 간격을 잠글 수 있는 방법이 없어집니다. (Gap Lock 은 이전 간격을 잠그는 것이므로)따라서, 마지막 record 이후의 값을 잠글 수 있기 위해 supremum pseudo record 를 두었을 것이라 예상합니다.supremum pseudo record(인덱스가 가질 수 있는 가상의 가장 큰 값) 에 대한 GAP Lock은 supremum pseudo record 이전의 간격들을 잠그기 때문입니다.이는 공식 문서의 다음과 같은 내용을 통해 뒷받침할 수 있을 것 같습니다.'Suppose that an index contains the values 10, 11, 13, and 20. The possible next-key locks for this index cover the following intervals, where a round bracket denotes exclusion of the interval endpoint and a square bracket denotes inclusion of the endpoint:'(negative infinity, 10] (10, 11] (11, 13] (13, 20] (20, positive infinity)For the last interval, the next-key lock locks the gap above the largest value in the index and the “supremum” pseudo-record having a value higher than any value actually in the index. The supremum is not a real index record, so, in effect, this next-key lock locks only the gap following the largest index value.- MySQL 공식문서 - Next Key Lock이를 바탕으로 '왜 supremum 레코드를 잠그나요 ?' 의 원인을 분석해보면 다음과 같습니다.- 우선 3,4 번 과정에서 id=137 인 index record를 읽습니다. - 이때 id는 PK 이므로 값이 유니크하기에, BETWEEN 136 AND 137 조건을 통해 137이라는 값을 찾았으면, 해당 값이 조건을 만족하는 가장 마지막 값이라는 것을 알 수 있습니다.- 따라서 id=138 을 더 이상 탐색하지 않고 종료하게 되는데, 이때 id=137은 해당 PK 인덱스(리프노드 페이지) 의 가장 마지막 값이므로, supremum 레코드를 이용하여 추가적인 간격을 잠구는 것이지 않을까 하는 생각이 들었습니다.위 부분에 대한 성욱님의 의견을 듣고 싶어 질문드렸습니다.---이와 별개로, 추가 궁금증이 있습니다.1. MySQL 공식 문서에서도 언급되었던 InnoDB performs row-level locking in such a way that when it searches or scans a table index, it sets shared or exclusive locks on the index records it encounters. 라는 문장에서 검색되거나 스캔된 의 의미가 잘 이해되지 않습니다.예를 들어, id를 PK로 갖는 어떤 테이블에서, id = 3 인 row 를 탐색하기 위해서는,B-tree의 root 부터 시작 ~ leaf 노드로 이동 후, leaf node의 페이지의 전체 데이터를 스캔해야 하지 않나요?예를 들어 id=3 인 record 가 들어있는 leaf 노드의 페이지에 id가 1 ~ 5 까지 있다고 하면,leaf 노드의 페이지로 진입하여 1부터 순차 탐색을 진행할 것 같은데, 그렇게 되면 1~5 까지의 index 값 사이에서 3을 탐색하는 데 1과 2를 먼저 찾을 것이므로, id가 1, 2, 3인 row가 모두 잠겨야 하지 않나 하는 생각이 들었습니다. 혹시 공식문서에서 언급한 검색 혹은 스캔된의 의미가, 조건에 사용된 인덱스가 걸린 필드 값만 확인하는 것은 포함하지 않는 것일까요?(ex - 위 예시에서 id가 1인 인덱스 확인조건에 부합되지 않으므로 넘어감. (스캔되었다고 보지 않음)id가 2인 인덱스 확인조건이 부합되지 않으므로 넘어감id가 3인 인덱스 확인조건에 부합되므로 나머지 값 읽어옴.)위 내용들에서, 제가 어떤 부분을 잘못 생각하고 있는지 알 수 있을까요?정말 좋은 강의와 글 공유해 주셔서 감사합니다.
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
측정 시간 차이
안녕하세요. 성능을 측정해보며 궁금증이 생겨 질문 드립니다. 같은 크기의 데이터에 대해 강사님께서 측정하신 시간이랑(강의에선 약 170ms) 제가 데이터그립으로 측정한 시간(약 80ms)에 꽤 차이가 있는데, 컴퓨터 사양이나 측정 툴에 따라 이 정도 차이가 있어도 무방한건가요?
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
Redis vs Memcached
안녕하세요. 강의 잘 듣고 있습니다!현재 개인 프로젝트에 Redis를 적용해보려고 합니다.구현하려는 기능은 주식 가격 요청 API로, 동일한 주식 종목을 여러 번 호출했을 때 캐시에서 값을 가져오는 로직입니다.Redis 외에도 Memcached라는 인메모리 캐시 서버가 있는데, 이 두 가지 서버 중 어떤 기준으로 선택하는 것이 좋을지 고민입니다.기술을 선택할 때, 근거를 명확히 하는 연습을 하는 것이 중요한가요?예를 들어, Redis는 리스트, 셋, 해시, 정렬된 셋 등 다양한 데이터 구조를 지원하고, 영속성 기능도 제공하는데, 이런 이유로 Redis를 선택해야 한다고 말할 수 있을까요?제가 구현하는 기능은 단순 조회 기능이라 Memcached도 적합할 수 있을 것 같지만, 이를 다른 사람들에게 설득할 근거와 이유는 어떻게 제시하는 것이 좋을까요?
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
redis 를 compose 로 묶어준 이유가 궁금합니다.
강의 내용 중, redis 를 docker-compose 로 묶어 한번에 띄우도록 설정한 모습을 확인할 수 있었습니다. 이렇게 되면 서버 코드의 변경점이 생겨 수동 재배포를 진행하게 될 때, docker-compose 파일로 실행하게 될 것 같습니다. redis 도 일종의 db라고 생각이 되는데, 서버의 코드가 업데이트 되면 redis 를 다시 docker로 띄운다는 가정이 생기는 것 같은데, 맞는 접근법인지 궁금합니다.초기 ec2 설정 단계에서 단순히 redis 를 설치해서 사용하면 되지 않나 라고 생각이 됩니다. 만약 캐시 전략의 변경이나, 캐시 데이터의 정합성? 문제가 우려된다면 key를 모두 날려주는 cli 를 실행시키는 방법이 더 유욜할 것 같은데, 강의 편의와 docker-compose 의 유용성을 설명하기 위한 강의 챕터인가요?
-
해결됨Real MySQL 시즌 1 - Part 1
ORDER BY가 필요한 이유
데이터 개수 기반 방식 (동등 조건 사용시) 에서 이미 인덱스를 설정 했기 때문에KEY ix_userid_id (user_id, id)따로 후에 ORDER BY id를 해주지 않아도 정렬이 되어 있을 것이라고 예상되는데 작성해 줘야 하는 이유가 무엇일까요
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
[실습] 인덱스 직접 설정해보기 / 성능 측정해보기 강의에서요.
-- 높은 재귀(반복) 횟수를 허용하도록 설정-- (아래에서 생성할 더미 데이터의 개수와 맞춰서 작성하면 된다.)SET SESSION cte_max_recursion_depth = 1000000; -- 더미 데이터 삽입 쿼리INSERT INTO users (name, age)WITH RECURSIVE cte (n) AS( SELECT 1 UNION ALL SELECT n + 1 FROM cte WHERE n < 1000000 -- 생성하고 싶은 더미 데이터의 개수)SELECT CONCAT('User', LPAD(n, 7, '0')), -- 'User' 다음에 7자리 숫자로 구성된 이름 생성 FLOOR(1 + RAND() * 1000) AS age -- 1부터 1000 사이의 랜덤 값으로 나이 생성FROM cte;-- 잘 생성됐는 지 확인SELECT COUNT(*) FROM users; SELECT n + 1 FROM cte WHERE n < 1000000 -- 생성하고 싶은 더미 데이터의 개수SELECT n + 1 이 먼저 실행되고 FROM cte WHERE n < 1000000 이부분이 실행되니까.n이 999999까지 실행되고 n + 1 =1000000 이니까 FROM cte WHERE n < 1000000이부분에 걸려서 1000000이 실행 안되는게 맞지 않나요?
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
커버링 인덱스(Covering Index)강의에서 질문이있습니다.
1.제가 비전공도 할수있는 데이터베이스강의를 듣고 이 강의를 듣고있는데요. user테이블에 name의 fk가 들어가는게 맞지 않나요? 빨간색 글씨로요. name id pk도 빨간색처럼 pk를 적어야 하지 않나요?아니면 name테이블과 name인덱스 테이블이 따로 있는건가요?2.인덱스가 새로운 테이블을 생성하는건가요?3.풀인덱스스캔 강의 질문있습니다.CREATE INDEX idx_name ON users (name); 이 구문이아래처럼 테이블을 미리 만드는건가요?
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
한 번에 너무 많은 데이터를 조회하는 SQL문 튜닝하기 질문입니다
만약 응답해야 되는 데이터는 "많은" 데이터인데데이터베이스에서 조회할 때는 LIMIT, WHERE로 나눠서 가져오고 애플리케이션 로직에서 합쳐서 응답하는게 나은가요?아니면 네트워크를 여러번 타는 것 보다는 이런 경우에는 한번에 가져오는게 더 나을까요?상황에 따라 다르겠지만,, 참고할만한 지침같은게 있을까 싶어서 여쭤봅니다!
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
ORDER BY 튜닝관련 문의
EXPLAIN ANALYZE SELECT * FROM users ORDER BY salary LIMIT 100; -> Limit: 100 row(s) (cost=100569 rows=100) (actual time=338..338 rows=100 loops=1) -> Sort: users.salary, limit input to 100 row(s) per chunk (cost=100569 rows=996636) (actual time=338..338 rows=100 loops=1) -> Table scan on users (cost=100569 rows=996636) (actual time=0.0672..250 rows=1e+6 loops=1) CREATE INDEX idx_salary ON users (salary); EXPLAIN ANALYZE SELECT * FROM users ORDER BY salary LIMIT 100; -> Limit: 100 row(s) (cost=0.0918 rows=100) (actual time=0.0709..0.253 rows=100 loops=1) -> Index scan on users using idx_salary (cost=0.0918 rows=100) (actual time=0.0692..0.249 rows=100 loops=1) 여기서 질문이 있는데요. 인덱스를 salary에 적용한 이후에도 analyze이후 actual time이 인덱스가 없을때와 별차이가 없어 보이는데요. 이건 mysql의 실행계획 표시에 오류가 있는걸까요?실제로 실행 속도는 향상은 돼었습니다.
-
미해결업무에 바로 쓰는 SQL 튜닝
다음과 같은 쿼리가 더 좋은 결과를 보이는데 이유가 뭔지 궁금합니다.
SELECT e.emp_id , s.avg_salary , s.max_salary , s.min_salary FROM EMP e, (select emp_id, ROUND(AVG(annual_salary), 0) avg_salary, ROUND(MAX(annual_salary), 0) max_salary, ROUND(MIN(annual_salary), 0) min_salary from SALARY where emp_id BETWEEN 10001 and 10100 GROUP BY emp_id) s WHERE e.emp_id = s.emp_id; 처음에 답을 안 보고 제가 개선해본 쿼리인데,필터링 조건을 salary에 넣어주고, 이걸 조인해서(emp의 primary key) 나오는 결과인데 미세하게 더 빠르네요.! 정답 쿼리가 조금 더 느린 이유는 salary 테이블을 3번 접근해서 그런거 같은데(index를 활용하더라도) 맞는지 궁금합니다.
-
미해결업무에 바로 쓰는 SQL 튜닝
rollup mariadb 11 ver 기준
SELECT REGION, GATE, COUNT(*) AS cntFROM ENTRY_RECORDWHERE REGION <> ''GROUP BY REGION, GATE WITH ROLLUP; -- 414ms ROLLUP 사용법이 달라서 구글이나 지피티에 서칭을 해봤습니다. 저처럼 안 되시는 분이 많을 거 같아서 올립니다.
-
미해결업무에 바로 쓰는 SQL 튜닝
use index, force index 힌트 질문
학습 환경은docker + mariadb 입니다.! 현재 힌트를 사용해서 Manager 테이블의 인덱스를 강제시켜서 실행시켰는데 다음과 같이 table full scan으로 변환되었습니다. 이거는 mariadb 내부적으로 hint가 올바르지 않다고 생각해 실행 계획을 바꾼걸까요?EXPLAIN SELECT e.FIRST_NAME, e.LAST_NAMEFROM EMP e,MANAGER m FORCE INDEX (PRIMARY)WHERE e.EMP_ID = m.EMP_ID ;