묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결업무에 바로 쓰는 SQL 튜닝
BNL Join 사용
SELECT EMP.emp_id, EMP.first_name, EMP.last_name, GRADE.grade_nameFROM GRADE, EMP; -- 카테시안 곱 mariadb로 실습을 진행했는데 hash join이 쓰이는게 아니라flat, BNL join을 사용한다고 되어 있네요?BNL Join은 MySQL이 인덱스가 없거나 사용할 수 없는 상황에서 기본적으로 사용하는 비효율적인 조인 알고리즘이라는데 원인이 무엇일까요?grade 테이블을 hash join table로 사용하지 않네요?
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
k6의 결과 해석
안녕하세요. 강의에서 k6를 실행하기 위해 30명의 가상유저가 10초동안 요청을 무한히 보내도록 설정하셨습니다. 그 결과 http_reqs 값이 1.66/s 가 나왔습니다. 이 값은 시스템의 대역폭 max값으로 이해해도 되나요?30명, 10초 설정값이 아니더라도 100명, 10초 설정값으로 진행해도 1.66/s 에 근사한 값이 나와야하는지 궁금합니다. (시스템이 처리할 수 있는 능력 의 Maximum은 항상 일정해야하지 않을까 라는 생각에 질문드립니다.)
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
강의 질문 있습니다
having에 있는 쿼리문을 where문으로 바꿔서 최적화 시키는 것은 이해가 갔습니다. 강의에는 인덱스 사용이 없어서 제가 한번 적용시켜보려고 멀티 컬럼(year, semester) 이렇게 넣고 explain 해보니 ref와 eq_ref가 떴는데도 불구하고 속도는 차이가 별반 다를게 없네요(2초 후반)인덱스를 어떻게 넣어야할지 알려주시면 감사합니다
-
미해결업무에 바로 쓰는 SQL 튜닝
select_type 에서 'simple' 경우 각각의 테이블이 '드라이빙' 또는 '드리븐' 인지 어떻게 알수 있나요?
안녕하세요. 우선 좋은 강의 만들어주셔서 정말 감사합니다 :)select_type 에서 'simple' 경우 각각의 테이블이 '드라이빙' 또는 '드리븐' 인지 어떻게 알수 있나요? 5-2. 실행계획 항목(1) -> 05:40 영상을 확인해보면 실행계획에서 table 필드 값 "e" 하고 "s" 가 있는데요.여기서 질문 2가지가 있습니다.질문1: 여기서 각각의 테이블이 '드라이빙' 또는 '드리븐' 인지 어떻게 알수 있나요?(실행 계획 통해 조회된 데이터 순서대로 판단하면 되는것인지... 궁금하네요.. 그런데 이걸로 100% 판단하기에 조금 어렵다고 들어서요...)질문2:만약 테이블 "e" 가 드라이빙 테이블이라고 가정시실질적으로 쿼리 수행할때 테이블 "e" 에 대한 where 절 조건을 이용해서 먼저 필터링 한다음에테이블 "s" 하고 조인 수행을 하는것인지 궁금 합니다.즉 드리아빙 테이블 조건절 이용해서 최대한 필터링 하고그다음 드이븐 테이블하고 조인을 수행하는지 궁금합니다.
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
Jackson2JsonRedisSerializer에 대한 궁금증
GenericJackson2JsonRedisSerializer를 사용할 때 저장되는 캐싱 데이터는 다음과 같았습니다."[{\"@class\":\"org.example.package..\",\"id\":\"123984\",\"title\":\"title0123984\",...,강의상에 나온 데이터 순서?? 와는 조금 다르게 package 다음에 @class 이후 데이터가 저장되는 구조가 나오는 것을 확인했습니다.이때 캐싱된 데이터를 조회하려고 하는데 com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected VALUE_STRING: need String, Number of Boolean value that contains type id (for subtype of java.lang.Object) 에러가 발생했습니다.너무 궁금해서 GenericJackson2JsonRedisSerializer에 대해서 알아보고 있는데, 여전히 에러가 발생하는 이유를 잘 모르겠습니다ㅜㅜ데이터가 캐싱되어서 저장될 때 구조가 다르게 들어가는 이유가 궁금합니다 아 물론 강의 후반부처럼 Jackson2JsonRedisSerializer를 사용했을 때는 정상적으로 동작했습니다.
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
사용된 어노테이션에 관한 질문
5:12분경 createdAt에서 @CreatedDate를 제외한 나머지 어노테이션들을 특별히 사용하신 이유가 있으실까요?
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
Redis 사용 방식에 대해서 질문 있습니다
안녕하세요 레디스를 공부하면서 궁금한게 있습니다.제가 토이프로젝트를 하면서 상품 검색 입력시 버튼 하나씩 누를때마다(이벤트 keyup 사용) 백엔드와 통신하여 입력창 하단에 자동완성 기능창을 만들려고 하고 있습니다.아무래도 버튼 하나씩 누를때마다 통신해야되니 빠르게 통신해야될 것 같아서 redis를 사용했습니다.상품 등록할 때 DB와 redis에 저장하고 (redis에는 상품 이름만 저장했습니다.)입력창 하단의 자동완성은 redis를 통해 상품 이름을 출력하고 출력된 상품이름을 선택시 DB를 통해서 상품 상세정보를 가져오는 식으로 했는데배운대로라면 Cache Aside 전략과 다른데 이럴때는 어떻게 구성해야되나요?아니면 SQL 튜닝만 잘해도 굳이 redis는 필요없는건지 궁금합니다.아무래도 버튼 누를때마다 통신하다보니 SQL은 느릴까봐 싶어 조바심이 나네요ㅠㅠ 알아보니 최근검색어나 인기검색어 같은 경우도 redis로 한다고하는데 이런것들도 굳이 출력하자면 DB로만 사용하여 출력이 될텐데 이게 Cache Aside 전략과 어떤 관계가 있는지 감이 안잡힙니다실무뛰면서 redis를 써본적이 없고 거의 db로만 해결하다보니 redis 사용예시를 잘 모르겠습니다
-
해결됨Real MySQL 시즌 1 - Part 1
[오타 제보] 선행 데이터를 기반으로 한 데이터 분석
안녕하세요~!강의에 오타가 있는 것 같아서 질문 드립니다.e2 서브쿼리에 user_id도 select 절에 포함되야 할 것 같아요!select sum(sign_up) as signed_up, sum(complete_purchase) as completed_purchase, (sum(complete_purchase) / sum(sign_up) * 100) as conversion_rate from ( -- 1월에 새로 가입한 유저 목록 select user_id, 1 as sign_up, min(created_at) as sign_up_time from user_events where event_type = 'SIGN_UP' and created_at >= '2024-01-01' and created_at < '2024-02-01' group by user_id ) e1 left join ( -- 처음 결제한 시점 정보 목록 select user_id, 1 as complete_purchase, min(created_at) as complete_purchase_time from user_events where event_type = 'COMPLETE_PURCHASE' group by user_id ) e2 on e2.user_id = e1.user_id and e2.complete_purchase_time >= e1.sign_up_time and e2.complete_purchase_time < date_add(e1.sign_up_time, interval 7 day);
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
aws elasticcache redis 툴 접속.
안녕하세요. 강의 잘 들었습니다.강의를 듣다보니 의문이 드는 점이 있어 질문드립니다.redis를 사용하다 보면 redisinsight같은 gui 툴을 통해 데이터를 확인하는데 운영관점에서 더 편한데요.aws elasticcache redis가 외부 로컬에서 접속이 안되면aws elasticcache는 데이터 확인을 툴로 못하는건가요? 실무에서 운영을 하다보면 분명 직접 데이터를 체크를 해야하는 케이스가 발생하는데 이걸 일일이 cli 명령어 찾는다는 것은 돈을 주고 aws 사용하는 고객입장에서는 너무 불편하다고 생각들어 문의드립니다.
-
해결됨Real MySQL 시즌 1 - Part 1
2강. VARCHAR(255) 저장되는 데이터의 길이 정보 질문
안녕하세요. 2강을 수강하면서 궁금한 점이 있어 질문 글 남깁니다. VARCHAR(30) vs VARCHAR(255) 둘 중에서 데이터 타입을 선택할 때 실제 사용하는 길이만큼만 명시해 주는 게 메모리 사용 효율을 높일 수 있다고 말씀해주셨는데요.VARCHAR(30)와 VARCHAR(255) 모두 저장되는 데이터의 길이 정보를 1 바이트(0~255 표현 가능)로 저장하는 것이 맞는걸까요?강의 자료에 VARCHAR(30) vs VARCHAR(255) 차이를 설명할 때 '디스크 공간 효율 차이도 미미하게 존재(1바이트 vs 2바이트)'라고 적혀 있어 VARCHAR(255)에서 저장되는 데이터 길이 정보에 2바이트의 공간을 할당한다는 의미로 이해되어서요. 좋은 강의 감사합니다.
-
해결됨Real MySQL 시즌 1 - Part 1
LIMIT, OFFSET을 사용하는 것과 범위 기반 방식의 성능 차이
안녕하세요. 강의 잘 듣고 있습니다. 제가 이해한바로는 LIMIT, OFFSET은 앞에서부터 data를 순차적으로 읽기때문에 성능 상 좋지 않고 이를 개선하기 위해 범위 기반 방식을 사용한다고 이해하였습니다.범위 기반 방식은 직접 ID 값을 지정 해주는 방식이며, id 기반으로 5000단위로 조회한다고 가정하면1회차: select * from users where id > 0 AND id <= 50002회차: select * from users where id > 5000 AND id <= 1000위와 같이 구현될 것으로 예상됩니다.관련해서 궁금한 점이 생겼는데요. 결국 두번째 쿼리를 실행 시 5000보다 큰 id를 찾는 과정에 시간이 소요될 것으로 예상되는데요, id가 index로 지정되어있어 LIMIT, OFFSET 방식보다 빠르게 찾을 수 있는 것인가요??LIMIT, OFFSET 방식 사용 시 어떤 컬럼이 index로 지정되어있는지와 상관없이 무조건 순차 탐색이 일어나는 것이고 범위 기반으로 조회 시 index로 서치하기때문에 더 빠르게 시작점을 탐색할 수 있다고 이해하면 될까요?
-
해결됨Real MySQL 시즌 1 - Part 2
unique index가 걸린 상황에서 s-lock, x-lock 질문
안녕하세요?먼저 좋은 강의 감사합니다. 7:50쯤 unique 제약조건이 걸린 상황에서 deadlock이 발생하는 경우에 질문이 있어서 글 남깁니다. 말씀주신 시나리오는unique index가 걸린 컬럼이 delete가 수행되면서, 동시에 insert into 구문이 들어오는 상황으로 말씀주셨는데요. unique index는 s-lock을 꼭 필요로 한다면,delete가 선행되지 않는 상황에서도 deadlock이 발생해야되는거 아닌가? 싶습니다. 상상하는 예시는 다음과 같습니다.tx-1 : begin; insert into tab(pk) values(2) (index 2 또는 그 범위에 s-lock) tx-2 : begin; insert into tab(pk) values(2) (index 2 또는 그 범위에 s-lock)tx-1 : commit; -> index 2에 x-lock을 잡으려고 하지만 tx-2가 s-lock을 잡고 있어서 잡을 수 없음 하지만, 실제로 테스트 해보았을 때는tx-1이 commit시에 정상적으로 insert 되고, tx-2는 duplicated key 오류를 반환합니다. 왜 이런지 알 수 있을까요?감사합니다 😃 다시 한 번 생각해보니, tx-1은 pk=2 가 없기 때문에 insert 후 x-lock으로 전환하고, tx-2는 x-lock으로 인해 lock_wait인 것 같습니다. 혹시 맞을까요?delete 가 선행된 경우는 이미 있는 레코드에 tx-1,2가 s-lock이을 잡으면서 delete가 commit된 시점에 tx-1,2가 x-lock을 획득하려는데서 dead lock이 발생하는 것이고요
-
해결됨비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
인덱스 많은 테이블에서 데이터 많아질 수록 insert 속도 증가
-- 테이블 A: 인덱스가 없는 테이블CREATE TABLE test_table_no_index (id INT AUTO_INCREMENT PRIMARY KEY,column1 INT,column2 INT,column3 INT,column4 INT,column5 INT,column6 INT,column7 INT,column8 INT,column9 INT,column10 INT); -- 테이블 B: 인덱스가 많은 테이블CREATE TABLE test_table_many_indexes (id INT AUTO_INCREMENT PRIMARY KEY,column1 INT,column2 INT,column3 INT,column4 INT,column5 INT,column6 INT,column7 INT,column8 INT,column9 INT,column10 INT); -- 각 컬럼에 인덱스를 추가CREATE INDEX idx_column1 ON test_table_many_indexes (column1);CREATE INDEX idx_column2 ON test_table_many_indexes (column2);CREATE INDEX idx_column3 ON test_table_many_indexes (column3);CREATE INDEX idx_column4 ON test_table_many_indexes (column4);CREATE INDEX idx_column5 ON test_table_many_indexes (column5);CREATE INDEX idx_column6 ON test_table_many_indexes (column6);CREATE INDEX idx_column7 ON test_table_many_indexes (column7);CREATE INDEX idx_column8 ON test_table_many_indexes (column8);CREATE INDEX idx_column9 ON test_table_many_indexes (column9);CREATE INDEX idx_column10 ON test_table_many_indexes (column10); -- 높은 재귀(반복) 횟수를 허용하도록 설정-- (아래에서 생성할 더미 데이터의 개수와 맞춰서 작성하면 된다.)SET SESSION cte_max_recursion_depth = 100000; -- 인덱스가 없는 테이블에 데이터 10만개 삽입INSERT INTO test_table_no_index (column1, column2, column3, column4, column5, column6, column7, column8, column9, column10)WITH RECURSIVE cte AS (SELECT 1 AS nUNION ALLSELECT n + 1 FROM cte WHERE n < 100000)SELECTFLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000)FROM cte; -- 인덱스가 많은 테이블에 데이터 10만개 삽입INSERT INTO test_table_many_indexes (column1, column2, column3, column4, column5, column6, column7, column8, column9, column10)WITH RECURSIVE cte AS (SELECT 1 AS nUNION ALLSELECT n + 1 FROM cte WHERE n < 100000)SELECTFLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000)FROM cte;를 그대로 사용했는데,index 가 많은 테이블에 데이터가 많아질 수록 insert 시 속도가 느려져야 될 것 같은데 느려지지 않는 것 같습니다. auto commit 모드이고 결과는 1차 : 10만개 삽입시 소요시간 3s2차 : 10만개 삽입시 소요시간 4s3차 : 10만개 삽입시 소요시간 4s4차 : 10만개 삽입시 소요시간 4s5차 : 10만개 삽입시 소요시간 4s6차 : 10만개 삽입시 소요시간 4s입니다. 뭔가 db 환경 문제일까요? db : MariaDBversion: 10.6.15 입니다.
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
Redis를 사용하는 이유
캐싱을 위해 Redis를 많이 사용한다고 생각하고 있었는데 SQL튜닝으로 해결되는 부분이 있는거군요! 그러면 일반적으로 현업에서 Redis를 사용하는 이유 중 어떤 이유로 가장 많이 사용하는지 여쭤볼 수 있을까요??
-
해결됨Real MySQL 시즌 1 - Part 1
MySQL Where절 내 조건의 순서
안녕하세요. MySQL 사용에 있어 Where절 내 조건의 순서가 쿼리 성능에 영향을 미치는지 여쭙고자 문의드립니다. 기본적으로는 옵티마이저가 쿼리를 최적화하기 때문에 Where절의 순서가 중요하지 않은 것으로 알고 있는데, DBMS에 따라 통계정보를 활용하는 데 있어 차이가 있다는 이야기를 들은 바 있어 호기심에 여쭤봅니다. (MySQL 공식문서에는 관련된 내용을 못 찾겠네요..)
-
해결됨Real MySQL 시즌 1 - Part 1
1강. delete marking된 데이터의 정리 주기는 어느 정도인가요?
안녕하세요. 좋은 강의 감사드립니다.강의 내용 중, VARCHAR타입 컬럼에 더 긴 문자열로 UPDATE 작업 시 이전 공간은 delete marking 된다고 하셨습니다.PostgreSQL의 경우에도 비슷한 매커니즘을 사용하기 때문에 VACUUM을 사용해 단편화 문제를 해결하는 것으로 알고 있고, 찾아보니 OPTIMIZE TABLE문을 통해 비슷한 작업을 할 수 있는 것 같습니다.PostgreSQL의 경우에는 VACUUM을 주기적으로 수동으로 해줘야 한다고 알고 있습니다만 MySQL의 경우에는 OPTIMIZE TABLE을 수동으로 해줄 필요가 있는지, 있다면 어느 정도 주기가 좋은지 궁금합니다.
-
해결됨Real MySQL 시즌 1 - Part 1
Mysql table avg_row_length
TEXT, LONGTEXT 타입 칼럼이 존재하는 테이블의 경우에 informatino_schema.TABLES에 존재하는 avg_row_length의 값은 LOB 칼럼들의 평균바이트 수도 같이 계산이 되는걸까요?
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
MariaDB 사용 시 EXPLAIN ANALYZE 이용 불가 문의
MariaDB 사용하고 있고 버전은 아래와 같은데 회사 DB로 버전 변경은 불가능한 상태입니다. 버전 : 10.4.12-6-MariaDB-enterprise-log EXPLAIN ANALYZE 사용 시 에러가 발생하여 구글링 해보니 MariaDB 에서는 사용이 불가능한 것 같더라고요.Mysql 에서 EXPLAIN ANALYZE 로 조회되는 내용을 동일하거나 유사하게 볼 수 있는 방법이 없을까요?
-
미해결Real MySQL 시즌 1 - Part 2
질문드립니다.
안녕하세요. 1,2 강의 전부 잘봤습니다!! 많은 도움 되었습니다.근데 강의에 대한 질문은 아닌데 도저히 여쭤볼 사람이 딱히 없어서요..현재 백엔드 취준생인데 프로젝트에 mysql 레플리카를 도입해서 master / slave1,2 아키텍처를 구성 하였습니다.--master[mysqld]log_bin = mysql-binserver_id = 10binlog_do_db = reservationdefault_authentication_plugin = mysql_native_password-- slave[mysqld]log_bin = mysql-binserver_id = 11relay_log = /var/lib/mysql/mysql-relay-binlog_slave_updates = ONread_only = ONdefault_authentication_plugin = mysql_native_password master와 slave에 맞게 설정을 해주고 master의 LOG_FILE, LOG_POS를 토대로 각각의 슬레이브에 설정하여Slave_IO_Running, Slave_SQL_Running slave1,2 각각 YES 인걸 확인하고 데이터 복제 및 인덱스 복제 까지 잘 동작하는것 까지 확인하였습니다. 그래서 백엔드 로직에서 ReadOnly 쿼리 비지니스로직은 SLAVE1,2의 dataSource가 할당 되어서 동작 하도록 구성하였고 실제로 테스트 해봤는데 master가 아닌 SLAVE1,2에서만 읽는것을 확인 하였습니다. 근데 여기서 문제인게 읽기작업에 대해서만 부하를 줘서 성능테스트를 진행하였는데 실제로 레플리카를 도입하기 이전 1대의 mysql 서버만 존재했을때가 성능이 20~30% 가 더좋게 나옵니다.저는 실제로 이미 쓰기작업을 끝낸 데이터에 대해 읽기 작업을 slave1,2가 트래픽을 분산(라운드 로빈 방식으로 정확히 50프로 확률로 분산) 하여 처리하니까 성능이 올라갈것으로 기대했는데 왜그런지 도저히 모르겠습니다.추가로 쓰기작업(JPA 긍정적 락), 읽기작업을 동시에 요청하는 부하테스트도 진행 했는데 물론 이 경우도 쓰기는 master만 진행하고 읽기작업은 나머지 slave1,2에서만 진행하는걸 확인했지만 성능 결과 1대의 mysql서버가 읽기,쓰기를 다 처리하는것이 성능이 더 좋았습니다. 그래서 제가 내린 결론은 만약 제가 한 테스트 방법이 잘못되지 않았다고 가정할 경우SLAVE 아키텍처를 가져 갈 경우 성능 향상보다는 부하를 분산시켜 최대 허용 TPS 향상 및 아키텍쳐의 안정성을더 해주는게 의미가 있다고 생각되고,만약에 SLAVE1,2를 두었는데 무조건 읽기작업의 성능향상이 이뤄져야 한다고 말씀 하시면 어떤 부분에서제가 무엇을 잘못 설정한걸 수 도있는지 아니면 어떤 이유가 존재할 수도 있는지 해결가능성이 있는 키워드정도 알려주시면 정말 감사하겠습니다. 추가로 상황에 따라 다르겠지만, 마스터 슬레이브 간의 동기화 문제를 해결하는 가장 보편적이고 추천 해주실만한 방법(제가 생각한 방법은 쓰기작업 직후의 읽기작업은 슬레이브가 아닌 마스터에서 하는 방식)이 있는지 알려주시면 정말 감사하겠습니다! 긴글 읽어주셔서 감사합니다.
-
해결됨Real MySQL 시즌 1 - Part 2
Real MySQL 시즌1 part 2 에피소드 16의 인덱스가 null인 컬럼을 포함한다는 것에 대한 질문
인덱스가 null인 컬럼을 포함하고 있고대상컬럼이 nullable column인지 not null column인지상관없이 어떤 인덱스를 읽어도 테이블의 정확한 레코드 수를 가져올 수 있다는게 무슨 뜻인지 이해가 잘안가서 질문 드립니다. 1. 인덱스가 null인 컬럼을 포함하고 있다는것은,인덱스가 존재하지 않는 컬럼을 의미하는 건가요 아니면 nullable 컬럼에 생성한 인덱스를 의미하는 건가요?2.nullable column이 존재하더라도 not null column에서 레코드를 읽는 덕분에 라는 건가요?