게시글
질문&답변
LIMIT, OFFSET을 사용하는 것과 범위 기반 방식의 성능 차이
안녕하세요.말씀하신 것처럼 users 테이블에 id가 인덱스로 지정돼있는 상황이라고 보시면 됩니다. 이 경우 범위 기반 방식 형태로 쿼리를 수행하면 조건에 만족하는 데이터만 읽게되므로, OFFSET이 증가할 수록 불필요하게 데이터를 많이 읽는 LIMIT & OFFSET 방식보다는 더 나은 것입니다.예를 들어, 동일하게 users 테이블에 id가 PK라고 가정하고, id가 1부터 10000까지의 데이터를 1000개씩 나눠서 조회한다고 가정해볼게요.LIMIT & OFFSET 방식의 경우 다음과 같이 쿼리를 실행하게 됩니다.1) SELECT * FROM users WHERE id > 0 AND id 0 AND id 0 AND id 반면, 범위 기반 방식의 경우 다음과 같이 쿼리를 실행하게 됩니다.1) SELECT * FROM users WHERE id > 0 AND id 1000 AND id 2000 AND id LIMIT & OFFSET 방식에서 첫 번째 쿼리는 1000개 데이터만을 읽지만, 두 번째 쿼리는 2000개, 세 번째 쿼리는 3000개로 점점 쿼리 처리 시 읽는 데이터 양이 늘어납니다.하지만 범위 기반 방식의 경우 쿼리 조건절에 아예 1000개씩 나눠진 범위가 조건으로 주어졌기 때문에, 각 쿼리마다 조건에 만족하는 1000개의 데이터만 읽게됩니다.결론적으로, 인덱스 사용 유무에 따른 차이라기 보다는 LIMIT & OFFSET은 실제 읽어야 하는 시작지점(OFFSET)을 찾기위해 조건에 만족하는 데이터를 정렬 순서대로 순차적으로 읽어서 시작지점을 찾은 후 LIMIT 절에 해당되는 건수만큼 추가로 더 읽게 되서 범위기반보다 성능이 더 좋지 않다고 볼 수 있습니다.질문 주셔서 감사하고, 추가로 궁금한 부분 있으시면 언제든지 다시 말씀해주세요.수강 감사드립니다. :)
- 0
- 2
- 141
질문&답변
2강. VARCHAR(255) 저장되는 데이터의 길이 정보 질문
안녕하세요. 답변이 늦었습니다.우선 VARCHAR 타입에서 데이터 길이 정보는 저장된 데이터가 255 바이트일때까지는 1바이트, 그 이상의 경우 2바이트가 할당됩니다. 그리고 VARCHAR(255)에서 255는 문자의 길이를 나타내며, 저장되는 바이트 수를 제한하는 것이 아닙니다.그렇기 때문에 질문주신 부분은 하나의 문자를 저장하는 데 몇 바이트를 필요로 하는지에 따라 달라진다고 볼 수 있으며, 이는 문자집합(Character Set)과 연관이 되어있습니다.만약 컬럼이 문자 당 1바이트씩 사용하는 latin1 문자집합으로 설정돼있다면, 말씀하신 것처럼 VARCHAR(30)과 VARCHAR(255) 모두 저장되는 데이터의 길이 정보가 1바이트일 수 있습니다. 그런데 만약 문자 당 1바이트 이상 사용하는 다른 문자집합이라면 VARCHAR(255)는 데이터의 길이 정보로 2바이트를 가지게 됩니다.구체적으로 utf8mb4 문자집합의 경우 최대 한 문자당 4바이트를 사용할 수 있는데요. 이 경우에는 VARCHAR(64)부터 데이터 길이 정보로 2바이트를 가질 수 있다고 보시면 됩니다.좋은 질문 주셔서 감사하고, 추가로 궁금한 부분 있으시면 언제든지 다시 말씀해주세요. :)수강 감사드립니다.
- 0
- 2
- 172
질문&답변
[오타 제보] 선행 데이터를 기반으로 한 데이터 분석
안녕하세요! 말씀하신 것처럼 e2 서브쿼리의 SELECT 절에 user_id 부분이 누락되었네요.강의에는 메모로 남겨두겠습니다.오타 제보 감사합니다!
- 0
- 1
- 77
질문&답변
6강. Top N 데이터 조회와 관련해 질문있습니다.
안녕하세요. 답변이 좀 늦었습니다.질문주신 내용들에 대해 각각 답변을 드리면,Q1) 만약 categories 테이블에 id가 1,2,3인 데이터가 있다면, 3번의 서브쿼리가 실행되고 각 결과를 전부 Union해서 최종 결과를 반환하게 되는건가요?대략 말씀하신 형태로 동작한다고 보시면 되는데요, 독립적으로 실행되는 서브쿼리보다는 조인과 같은 형태로 처리된다고 생각해주시면 좋을 것 같습니다.Q2) LIMIT 3을 제거했을 때 내림차순 정렬이 안된 상태로 데이터가 반환되는데요. 그 이유가 뭔지 알 수 있을까요?이건 쿼리의 실행계획을 봐야하는데요. LIMIT 절이 있을 때는 (category_id, views)로 구성된 인덱스를 뒤에서부터 읽다보니(Backward index scan) 내림차순 정렬로 데이터가 반환됐지만 LIMIT 절이 없는 경우에는 해당 인덱스를 정순으로 스캔하면서 데이터를 읽어와서 오름차순 정렬인 것으로 예상됩니다.사실 이 부분은 현재 제일 바깥쪽 쿼리에 ORDER BY 절이 없기때문에, 쿼리 처리 방식에 따라 최종적인 결과 데이터의 정렬 순서가 예상한 것과는 다를 수 있습니다. 그래서 어떻게 처리되던지 항상 내림차순 정렬을 원하시면 제일 바깥쪽 쿼리에 ORDER BY 절을 명시해주시는 것이 좋습니다. 답변 읽어보시고 혹시 더 추가로 궁금한 부분 있으시면 말씀해주세요!감사합니다.
- 0
- 2
- 123
질문&답변
12강. LEFT JOIN 사용 방법 준수 5:42
안녕하세요.문의주셨던 부분 관련해서 제가 말씀드리고자 했던 요지는LEFT JOIN을 굳이 사용하지 않아도 되는 경우에는 JOIN을 제거본래 목적이 LEFT JOIN이 아닌 INNER JOIN이 맞다면, 명시적으로 INNER JOIN으로 변경입니다!혹시 추가로 궁금한 부분 등이 있으시면 편하게 말씀해주세요.감사합니다.
- 0
- 2
- 164
질문&답변
JPA 사용시 테이블수정에 궁금한점이있습니다
안녕하세요.사용하시는 컬럼에 저장될 수 있는 값의 최대 길이를 비교적 명확하게 파악하고 계신 상황이라면(혹은 파악하실 수 있는 상황이라면), 강의에서 설명드린 것과 같이 DB 서버 자원 사용 효율을 위해 모든 문자열 컬럼들을 VARCHAR(255)로 사용하시기 보다는 실제 사용되는 길이만큼만 지정해서 사용하시는 것을 권고드립니다.감사합니다.
- 0
- 1
- 166
질문&답변
복합인덱스 정렬
안녕하세요.테이블에 (finished_at, id)로 구성된 인덱스가 있다고 가정했을 때, 공유해주신 쿼리가 실행되면 인덱스 데이터에서 finished_at이 '시작날짜' 값 이상인 데이터들을 쭉 스캔하면서 id > 8인 데이터들을 확인하고 이렇게 확인된 데이터가 LIMIT 절에 주어진 30건을 만족하면 쿼리는 종료됩니다.LIMIT 절이 주어지지 않으면 말씀하신 것처럼 기본적으로 finished_at 컬럼에 주어진 조건 범위로 인덱스 데이터를 전부 스캔할 것으로 예상합니다. 쭉 스캔하면서 id 컬럼에 주어진 조건을 만족하는지 추가로 확인하게 됩니다.그리고 이러한 동작 방식은 id 컬럼에 대한 조건이 범위 조건이 아니고 동등조건이라 하더라도, 인덱스의 선두 컬럼인 finished_at 컬럼에 대해 범위 조건이 주어졌기 때문에 동일하게 동작합니다.그럼 추가로 궁금한 부분 있으시면 다시 말씀해주세요.감사합니다.
- 0
- 1
- 137
질문&답변
LATERAL 키워드는 mysql8 에서 잘 지원 되나요?
안녕하세요.MariaDB에서는 쿼리에서 LATERAL 키워드 사용이 불가하고, 내부적으로 Lateral Derived 최적화를 지원하는 것으로 보입니다.저희 강의 내용은 MySQL 8.0을 기반으로 하므로, 강의에서 소개된 기능 등을 테스트하실 때는 가능하시다면 MySQL 8.0 버전대를 설치해서 테스트해봐주시면 좋을 것 같습니다.추가로 궁금한 부분 있으시면 다시 말씀해주세요.감사합니다.
- 0
- 1
- 189
질문&답변
안녕하세요. 인덱스 관련 질문 있습니다.
안녕하세요. 답변이 늦었습니다.인덱스가 (account_type, joined_at)과 같이 존재할 때, 쿼리 WHERE 절에는 (joined_at, account_type) 순서로 조건이 주어졌다고해서 인덱스를 활용하지 못하는 것은 아닙니다.인덱스를 구성하는 컬럼들이 모두 조건으로 주어져있기 때문에 인덱스는 당연히 사용이 가능합니다.쿼리 WHERE 절에 나열된 순서가 인덱스 내 컬럼 순서와 다르더라도 MySQL 옵티마이저는 인덱스를 사용할 수 있는 조건들을 추려내서 인덱스를 활용하는 최적화를 수행하기 때문에, 순서는 크게 중요하지 않고 인덱스를 구성하고 있는 컬럼들이 조건으로 주어져 있는지가 더 중요하다고 봐주시면 좋을 것 같아요.그리고 추가적으로 쿼리에서 컬럼들에 주어진 조건 형태에 따라 인덱스 내 컬럼 순서가 쿼리 처리 효율에 영향을 줄 수 있는데요.예를 들어, 아래와 같이 쿼리에서 인덱스를 구성하는 컬럼들 모두 동등 조건으로 조건값이 주어진 경우에는 인덱스 내의 컬럼 순서는 어떤 순서든 크게 상관이 없습니다.SELECT * FROM tab1 WHERE account_type = ? AND joined_at = ?그러나 아래와 같이 joined_at이 동등 조건이 아닌 범위 조건으로 사용된 경우에는, 인덱스 내 컬럼 순서가 (account_type, joined_at) 인 것이 좋습니다.SELECT * FROM tab1 WHERE account_type = ? AND joined_at >= ? AND joined_at (account_type, joined_at) 으로 인덱스가 구성돼있는 경우, 쿼리 처리 시 인덱스에서 실제 조건에 만족하는 인덱스 데이터들만 스캔하지만, (joined_at, account_type) 순서로 인덱스가 구성돼있는 경우 인덱스 선두에 위치한 joined_at 조건 범위에 속한 인덱스 데이터를 모두 스캔하게 되기 때문입니다.관련해서 모든 내용을 댓글로 다 설명드리기는 어려워서.. 혹시 Real MySQL 8.0 책 1권을 가지고 계시다면, "8.3.7.1 비교 조건의 종류와 효율성" 부분을 읽어보시는 것을 추천드립니다.추가로 궁금한 부분 있으시면 다시 말씀해주세요.감사합니다.
- 0
- 2
- 297
질문&답변
LATEAL 사용 관련 질문
안녕하세요. 답변이 늦었습니다.일단 질문 주신 내용으로 미루어보았을 때, 일반 서브쿼리와 Lateral Derived Table을 동일한 서브쿼리 형태로 인지하고 계신 것 같은 느낌을 받았는데요.일반 서브쿼리와 Lateral Derived Table은 사용 형태과 처리 방식이 완전히 다릅니다. 특히나 Lateral Dervied Table은 조인 형태로도 사용할 수 있고, 이로 인해 일반 서브쿼리 보다 유연한 쿼리 작성이 가능하고 DB 내부적으로도 좀 더 최적화된 형태로 처리될 수 있습니다. 그래서 제 개인적으로는 언급해주신 권장 사항들이 어떤 경우든 항상 옳다고 볼 수는 없을 것 같아요.Lateral을 사용하면 좋은 대표적인 경우들에 대해서는 제가 강의에 언급해둔 터라, 강의에 나와있는 예시들을 참고해주시면 좋을 것 같습니다.혹시 추가로 더 궁금한 부분 있으면 다시 말씀해주세요!감사합니다.
- 0
- 2
- 435