묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
WHERE A OR B 에서 인덱스 걸기
안녕하세요, 좋은 강의 제공해 주셔서 감사합니다.[실습] WHERE문에 인덱스를 걸기 vs ORDER BY문에 인덱스를 걸기 강의 에서 질문이 있습니다. 만일 created_at 과 department 가 AND 가 아닌 OR 조건이 주어지면, 데이터 엑세스가 더 많은것에 인덱스를 거는것이 좋을까요?? SELECT * FROM users WHERE created_at >= DATE_SUB(NOW(), INTERVAL 3 DAY) OR department = 'Sales' -- AND 대신 OR ORDER BY salary LIMIT 100;
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
질문이있습니다.
제가 선생님 강의를보고테이블에 천만개의 데이터를 넣고 인덱스를 테스트하고있었는데요, 2가지 질문이 생겼습니다. 질문다음과 같이 익스플레인 에널라이즈를 하면 소요시간이 약 704ms 으로 나옵니다. 그런데 익스플레인 에널라이즈만 제거하고 다시 셀렉트를 하면 소요시간이 1.494로 증가하는데 단순 조회 쿼리와 익스플레인 에널라이즈 쿼리가 서로 다르게 동작해서 그런건가요? 분석때문에 에널라이즈쪽이 더 오래걸릴까 싶었는데 오히려 반대라서 왜 이런현상이 발생하는지 궁금합니다.-> Filter: ((reservation.userId = 389788) or (reservation.seatId = 50)) (cost=11192 rows=10272) (actual time=2.33..678 rows=10271 loops=1) -> Deduplicate rows sorted by row ID (cost=11192 rows=10272) (actual time=2.3..676 rows=10271 loops=1) -> Index range scan on reservation using idx_user over (userId = 389788) (cost=1.11 rows=1) (actual time=0.115..0.115 rows=0 loops=1) -> Index range scan on reservation using idx_seat over (seatId = 50) (cost=1038 rows=10271) (actual time=0.0497..2.77 rows=10271 loops=1) 질문제가 다음과 같은 쿼리에 인덱스를 걸며 테스트해보니복합인덱스 ( userId,seatId or reverse ) 는 전혀 인덱스를 활용하지않고 단일 인덱스를 각각 지정했을 경우에만 아래와같이 인덱스를 병합해서 사용하더라구요. 이렇게 속도를 절반으로 떨어뜨렸는데 아무래도 데이터가 천만개라 그런가 여전히 1초 이상의 시간이 소요되어서 선생님이 보셨을때 여기서 더 개선해볼 방법이 있는지 궁금합니다.where쪽을 건드려 보자니 둘중 하나라도 충족되면 가져와야하는 상황이라면 or 말고 다른건 떠오르질않았습니다.(에널라이즈는 시간이 1초 미만으로 나오지만 실제로 쿼리 돌려보면 소요시간 1.4초 이상으로 찍힙니다. ) CREATE INDEX idx_user ON reservation_entity(userId); CREATE INDEX idx_seat ON reservation_entity(seatId); SELECT `reservation`.`createdAt` AS `reservation_createdAt`, `reservation`.`updatedAt` AS `reservation_updatedAt`, `reservation`.`deletedAt` AS `reservation_deletedAt`, `reservation`.`id` AS `reservation_id`, `reservation`.`userId` AS `reservation_userId`, `reservation`.`concertId` AS `reservation_concertId`, `reservation`.`seatId` AS `reservation_seatId`, `reservation`.`status` AS `reservation_status`, `reservation`.`price` AS `reservation_price`, `reservation`.`concertName` AS `reservation_concertName`, `reservation`.`seatNumber` AS `reservation_seatNumber`, `reservation`.`openAt` AS `reservation_openAt`, `reservation`.`closeAt` AS `reservation_closeAt` FROM `reservation_entity` `reservation` WHERE `reservation`.`userId` = 389788 OR `reservation`.`seatId` = 50; -> Filter: ((reservation.userId = 389788) or (reservation.seatId = 50)) (cost=11192 rows=10272) (actual time=2.33..678 rows=10271 loops=1) -> Deduplicate rows sorted by row ID (cost=11192 rows=10272) (actual time=2.3..676 rows=10271 loops=1) -> Index range scan on reservation using idx_user over (userId = 389788) (cost=1.11 rows=1) (actual time=0.115..0.115 rows=0 loops=1) -> Index range scan on reservation using idx_seat over (seatId = 50) (cost=1038 rows=10271) (actual time=0.0497..2.77 rows=10271 loops=1)
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
테이블에 기본키가 없을때
강의를 듣다 궁금한 점이 생겨서 글을 남김니다.보통 테이블을 생성할때 당연하게 pk를 지정해 주었는데 pk가 없는 테이블도 생성을 하나요? 생성은 되는것 같은데 똑같이 테스트를 해보니 따로 정렬한는 기준이 없어서 그런지 id 7번을 2번으로 바꿔도 들어온 순서대로 위치가 맨 마지막에 있는것을 확인했습니다. pk가 없는 테이블도 있는지 있으면 성능이라던지 차이점이 뭔지 궁금합니다.
-
미해결비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
질문있어요!!!
인덱스를 생성할때, 오름차순 - 내림차순도 설정할수있는데,날짜 기준으로 '최신 날짜 기준'으로 자주 조회하는 쿼리일 때,인덱스를 날짜 기준으로 내림차순으로 만들면 쿼리에 더 효과가 있는 걸까요?아니면 정렬 설정 상관없이 '옵티마이저'가 알아서 판단해서 조회를 하는 건가요?? 그리고강의 너무 유익하게 듣고있습니다. 늘 좋은 강의 감사합니다
-
해결됨Real MySQL 시즌 1 - Part 1
전체 count(*) 내용에 대해서 문의 드립니다.
안녕 하세요..실제로 count(*) 때문에 고민이 많습니다.게시판 형태의 화면이 있는데요..데이터가 약 250만건 정도 입니다.조인된 테이블은 6개 이고요..테이블 6개를 조인 해서 보여주다 보니 검색 조건은 매우 많습니다.페이징을 20개씩 10페이지씩 보여주고 있는데요..강의 내용 대로 전체 count(*) 때문에 속도가 느립니다.전체 갯수를 소스 상에 써 놓고 테스트를 해보면 속도가 느리지 않거든여..강의를 보기 전에도 테스트 해본 결과 속도는 전체 갯수의 count(*) 문제 라고 판단 하고 있었는데요..시스템의 로우 갯수를 사용 하는 방법이나리눅스의 cron 으로 각 테이블의 갯수를 10분 단위로 입력 하는 것 등..여러가지 생각을 해보았으나..검색 때문에 포기 했습니다.검색을 하면 검색 결과에 대한 전체건수가 나와야 하는데..이건 실시간 아니면 파악할 수가 없으니까요..강의를 보면서 힌트를 얻고자 했으나..대략적인 건수..임의의 페이지 표기 통계 이용대략 이해는 됩니다만..만일 검색을 하게 되면..모두 사용 할 수 없는 것 아닌가요?강의 에서 얘기한 것들은 모두 아무런 조건이 없을 경우 이고..예를 들어 검색 조건이 10가지 정도 될 경우 어떤 조건으로 검색할 지 모르는 상황인데대략적인 건수를 표시할 수도 없고 임의의 페이지를 표시할 수도 없습니다.예를 들어 검색 조건 시 1개도 없는 경우도 있을 수 있는데..어떻게 대략적인 건수를 표시를 할 것이며..임의의 페이지를 표시 할 수 있을까요..검색결과가 1건도 나오지 않았는데 페이지를 1~10 까지 대략적으로 표시할 수는 없는 것 아닌가요?통계이용은 검색 시 더더욱 사용할 수 없고요..제시하신 방법으로는 문제가 해결 될 것 같지 않은데..제가 잘못 생각 하고 있는 걸까요?제 생각이 틀렸으면 좋겠습니다만..방법이 있을까요?
-
해결됨Real MySQL 시즌 1 - Part 1
없는데이터에 select ... for update 쿼리시에 Lock
안녕하세요.예시를 위해 테이블명을 변경했습니다. 도메인상 이해안되도 이해부탁드립니다..!바로 질문으로 들어가면 아래에 쿼리를 발생시키면 supremum pseudo-record 락이 생기게 됩니다. 하지만 여기서 다른 세션에서 아래 쿼리를 똑같이 실행하면 select for update에서 락대기가 걸릴거라고 예상했는데 START TRANSACTION; #1 #reader_id+name 조합으로 유니크인덱스 사용중 SELECT * FROM book b WHERE reader_id = 21 AND name = 'ABC' FOR UPDATE; #2 INSERT INTO book VALUES (null, 'ABC', 21); #3아래 처럼 같은 락이 추가됩니다. 그래서 두 세션중 어느세션에서 insert 쿼리를 입력하든 Lock 대기가 걸리게됩니다. select에서 락대기가 걸리길 바랬는데 insert를 해야 락대기가 걸리는 이유가 무엇인가요?답변 미리 감사합니다.
-
해결됨비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
실행 계획 type / 정렬 방식
안녕하세요 강사님! 실행 계획 type에 대해서 궁금한 점이 있습니다. ref가 UNIQUE가 아닌 컬럼의 인덱스를 사용한 경우라고 해주셨는데, 그러면 UNIQUE가 아닌 컬럼의 인덱스이지만 index나 range의 경우에 해당하면 해당 타입으로 표시되는 거고 저 둘(index, range)이 아닐 때, ref 타입으로 표시되는 걸까요? 그리고 한 가지 더 궁금한 점이 있는데, 만약 데이터를 조회한 결과들을 바로 View로 보내는 게 아니고 자바 코드를 사용한 계산을 통해 가공해야 하는 상황이라면 굳이 ORDER BY를 쓰지 않고, 데이터 조회 후, Collections.sort()와 같은 자바 코드로 정렬하는 편이 나을까요?
-
해결됨Real MySQL 시즌 1 - Part 2
파티셔닝의 자원 사용 효율 증가 관련 질문
"테이블 파티셔닝이 필요한 이유"중에 "자원 사용 효율 증가 및 쿼리 성능 향상"을 언급주셨습니다.예를들어 최근에 저장된 데이터들 위주로 조회하는 경우 파티션 프루닝을 통해 최근 데이터만 접근하니까 효율적이라는 내용인데요, 효율적인 부분이 제가 생각했을 때 아래 2가지 정도인 것 같습니다.테이블의 모든 row를 접근 안해도 되고 더 적은 데이터만 읽어도 됨버퍼풀에 자주 사용되는 일부 데이터만 로드해도 됨여기서 질문이 있습니다. 파티셔닝키를 대상으로 인덱스를 걸면, 마찬가지로 최근 데이터만 접근가능하고, 버퍼풀에 최근 데이터만 올라가지 않나요?인덱스를 거는 방식이 파티셔닝을 사용하는 것에 비해 어떤 점에서 부족한가요?
-
해결됨Real MySQL 시즌 1 - Part 2
INSERT에서 shared lock을 거는 이유 질문
"DeadLock 예시(2)"에서 INSERT구문이 UNIQUE를 보장하기위해 shared lock을 걸고 확인한다고하였는데요, 그냥 처음부터 exclusive lock을 걸고 값을 확인하게 구현할 수도 있을 것 같은데, 그렇게 안되어있는 특별한 이유가 있을까요?exclusive lock을 건 상태에서는 값이 있는지 확인이 불가능하다 (shared lock을 걸었을때만 가능하다)그냥 어쩌다보니 MySQL이 그렇게 구현되어있다.lock경합을 줄이기위한 의도로 이렇게 구현했다?제가 생각나는 이유는 위 2개 정도인데, 어떤 이유인지 아실까요?
-
해결됨Real MySQL 시즌 1 - Part 2
안녕하세요. 인덱스 관련 질문 있습니다.
에피소드 15에서 복합 인덱스의 경우 순서가 중요하다고 하셨는데요.그럼 인덱스 생성 시 (account_type, joined_at) 와 같은 순서일때 조건에 joined_at account_type 순서로 주어지면 인덱스를 활용하지 못하는게 맞을까요??
-
해결됨Real MySQL 시즌 1 - Part 2
테이블이 1:N 구조에서 N쪽 테이블에 유니크 제약조건에 의한 오류발생 회피 방법이 뭘까요?
안녕하세요. 질문 드립니다.1:N 구조의 웹 어플리케이션입니다.종종 동일한 insert 요청이 짧은 시간에 발생 합니다.insert는 N(child) 테이블에 되어야 합니다.해당 테이블에는 유니크 제약조건이 걸려있어서 중복 데이터는 절대로 insert 되지 않지만 동일 요청에 의해서 DeadLock이 발생하고 있습니다.(물론 빈도는 많지 않습니다.)실행 순서는 이렇게 됩니다.Parent테이블의 id를 이용해서 join 쿼리로 select 합니다. (child 테이블 존재 여부 확인)child 테이블에 데이터가 존재한다면 수량 증가, 없다면 insert를 합니다.이 때 데이터가 없는 상황에서 select-insert 요청이 서로다른 tx에서 발생할 때 데드락이 발생합니다.이 경우 어떤 전략으로 회피할 수 있을까요?유니크 제약 조건에 의해서 중복 데이터가 생기는건 방지되고 있고, 데드락 자체가 하루 한 건 정도 발생하고 있어서 시스템 운영상에서는 문제가 없으나 어떤 해결책이 있을지 궁금합니다.
-
미해결Real MySQL 시즌 1 - Part 1
LATEAL 사용 관련 질문
안녕하세요. 현재 강의를 수강중인 학생입니다. RATERAL 사용 관련되어 질문이 있어 글 남겨드립니다. 잘못된 지식일 수 있지만, 서브쿼리를 사용하면 DBMS에서 지원하는 최적화를 지원받지 못해 서브쿼리를 사용하는 것보다는 최대한 조인을 사용하거나 차라리 쿼리를 나눠서 사용하는 것을 권장한다고 알고 있었습니다. 그런데 해당 강의를 수강하고 LATERAL의 사용을 적극 권장하셔서 제가 알고 있는 지식과 충돌하는 것 같습니다 혹시 어떤 경우에 LATERAL을 사용 하는 것이 좋을 지 여쭤보고자 글을 작성합니다.감사합니다.
-
미해결Real MySQL 시즌 1 - Part 1
수업과는 상관 없을 수 있는 질문인데요..
안녕 하세요..이런 질문을 드려도 될까 모르겠습니다만..현재 운영 되는 사이트는 ms-sql 로 bak 파일 기준 약 50기가 정도 됩니다.사이트를 개편 하려고 하고 있는데요..mysql 로 바꾸는 것을 논의 중 입니다.처음 부터 데이터가 50기가 가 입력 되는 것은 아니고..운영 하면서 데이터가 늘어날텐데.. 경험 상 50기가 정도 될 것으로 예상 됩니다.특정 테이블은 몇천만건의 데이터가 입력 될 수도 있는데요..mysql 이나 mariadb 로 이 정도의 데이터베이스를 운영 할 수 있을지..사이트 속도 에는 큰 문제가 없을지..조언 부탁 드립니다.감사 합니다.
-
해결됨Real MySQL 시즌 1 - Part 2
복합 인덱스의 컬럼중 선행 컬럼을 조건에서 누락해도 인덱스가 사용될 수도 있나요?
안녕하세요. 이제 2회차로 다시 잘 보고 있는 수강생입니다 🙂 Ep15를 보던 중 복합 인덱스의 컬럼들 중 선행컬럼을 조건에서 누락할 경우 풀 스캔이 될 수 있다고해서 직접 쿼리를 실행해봤습니다. 환경: MySQL 8.2.0쿼리explain select * from users where joined_at > '2022-07-24 00:00:00';결과8.0.21버전부터는 인덱스 스킵 스캔을 통해 선행 컬럼이 조건에 포함되지 않아도 후속 컬럼을 이용해 인덱스 일부 활용이 가능하다고 하는데 이 때문에 위와 같은 실행 계획나 나온걸까요?
-
해결됨Real MySQL 시즌 1 - Part 2
SKIP LOCKED 부분에서 INNER JOIN이 아니고 LEFT JOIN이 걸릴수 있다면
예제에서는 WHERE 절 때문에 LEFT JOIN이 INNER JOIN으로 최적화되는 것으로 알고 있지만 만약에 LEFT JOIN으로 걸릴 수 있는 쿼리라면 SKIP LOCKED 의 잠금 경합의 결과가 달라질 수도 있나요?
-
해결됨Real MySQL 시즌 1 - Part 1
강의 자료는 따로 제공되지 않나요??
질문 내용은 제목 그대로 입니다!
-
해결됨Real MySQL 시즌 1 - Part 1
조건 없는 COUNT(*)에 대한 궁금증
안녕하세요, 강의 잘 듣고 있습니다. 강의와 책을 동시에 보면서, 학습을 하고 있습니다. 근데 강의와 도서에서 설명하는 내용에 다른점이 있는 것 같아서 질문드립니다. REAL MySQL 8.0 (2권) 중 11.4.6 COUNT() 절에서는 아래와 같이 설명되어 있습니다.MyISAM 스토리지 엔진을 사용하는 테이블은 항상 테이블의 메타 정보에 전체 레코드 건수를 관리한다. 그래서 "SELECT COUNT(*) FROM tb_table"과 같이 WHERE 조건이 없는 COUNT(*) 쿼리는 MySQL 서버가 실제 레코드 건수를 세어 보지 않아도 바로 결과를 반환할 수 있기 때문에 빠르게 처리된다.하지만, 강의 Ep.03 COUNT(*) vs COUNT(DISTINCT) 튜닝 에서는 WHERE 절 없는 COUNT(*) 는 제거 대상이라고 설명을 해주셨습니다. 책의 내용처럼 메타 정보에서 가져온다고 한다면 굳이 제거 대상이 될 것 같지는 않은데, 혹시 제가 놓친 배경이 있었을까요? 아니면 이게 뭔가 이분법적인 차원에서 접근하기에는 어려운 내용일까요?
-
해결됨Real MySQL 시즌 1 - Part 2
단일 인덱스 크기, 전체 인덱스 크기 구하는 계산식
안녕하세요!14분 쯤 나오는 단일 인덱스 크기와 전체 인덱스 크기가 얼마인지 나오는데, 각각 구하는 계산식을 알 수 있을까요..?어떻게 8바이트가 1억건의 테이블이 있을때 6GB가 되는지 잘 모르겠습니다..8바이트 x 1억 레코드 = 800MB800MB / 1000 = 0.8GB인줄알았는데 따로 계산법이 있는걸가요?추가적으로 필요인스턴스 관련해서 aws에서 계산해보고싶은데 aws요금 계산기에서 Aurora MySQL 서비스 로 검색하면되는게 맞을까요? 서비스 찾기에 Aurora MySQL 검색해도 결과없음으로 나와서요..ㅠㅠ
-
해결됨Real MySQL 시즌 1 - Part 2
primary key에 시간, uuid로 복합키로 설정하는 경우
안녕하세요!좋은 강의 감사합니다!이력 테이블의 대용량 데이터를 저장하기 위해pk값 설정 시 정수형은 제한이 있다고 생각해서시간+uuid로 복합키를 설정하려고 하는데요! 레인지 파티션도 사용하려구 하구요! 이렇게 할 경우 결국엔 String타입으로 저장되서 클러스터링 인덱스가 제대로 저장이 될까? 고민이 있었는데요!이런 고민을 갖고 강의를 보게 되었는데, 강의 내용을 참고해보면uuid값이 정수형보다 길어서 pk로 사용할 경우메모리를 많이 차지해서 메모리크기가 큰 인스턴스를 사용해야 하므로 비용처리가 드는걸로 이해했습니다.uuid대신 snowflake나 sonyflake 라이브러리로 대체하는게 더 좋다고 말씀해주셨는데, 해당 라이브러리가 망하거나(?) 제대로 작동을 안할경우의 위험성도 고려해봐야할것 같다는 생각이 들어서요! 제가 요 라이브러리는 잘 몰라서 여쭤보고자합니다!그래서 질문은 아래 3가지 입니다!Q1. 시간+uuid로 복합키로 pk를 설정하거나, 애플리케이션단에서 시간+uuid만든 String 타입을 pk를 설정하는것보다, snowflake 라이브러리 하나만 사용하는게 더 메모리가 효율적인게 맞을까요?Q2. snowflake가 실제로 현업에서도 많이 쓰이는지 해당 라이브러리가 추후에 제대로 작동을 안할 경우에는 어떻게 대처를 해야 하는지 궁금합니다!Q3. 추가적으로 uuid관련 내용이 Real Mysql 2권 중 어디에 있는지도 궁금합니다! 목차에서는 찾을 수가 없어서요 ㅠㅠ
-
해결됨Real MySQL 시즌 1 - Part 1
Select for update locking
Select for update 시 lock 을 걸어 원 데이터를 버장힌다는 것은 이해 하였습니다그렇다면 a|b 가 동시 접근 하여 서로 다른 값으로 변경하려는 부분은 없고 동일 프로세스가 두번 진입 할 수 있다고 가정한다면어차피 update 시 xlock이 row에 대하여 획득하니select for update 는 필요없는게 맞다라고 이해를 했습니다이 부분이 맞을까요?