728x90
장점
- SQL Injection 방지
- 쿼리 파싱 비용 감소 (2번 째 이후 실행할 떄를 말함)
단점
- 메모리 사용량 증가
- 2번의 Network round-trip이 필요하다 (첫번째 실행, PreparedStatement를 하기위해 한번(최초에), 쿼리를 실행하기 위해 한번))
- execution plan은 캐시되지 않는다, parse tree만 캐시된다.
- 캐시된 PreparedStatement 는 커넥션 내에서만 공유된다.
- 100개의 connection에서 동일한 preparedStatement를 실행한다고 해도 mysql server에서는 1개가 아니라 100개의 preparedStatement를 가지고 있게 된다.
PreparedStatement의 비밀
- MySQL의 PreparedStatement
- Client Side PreparedStatement = 아직 지원하지 않을 때 emulate하기위해 존재했었다.
- Server Side PreparedStatement
- 모두 SQL Injection 을 막을 수 있다.
JDBC Server Side PreparedStatement는
- useServerPrepStmts=TRUE인 경우에만 작동한다
- useServerPrepStmsts=FALSE (기본 값)
- ORM에서는 TRUE로 기본 설정되는 경우가 많다
케이스 1번 부터 실행하면 매번 반복 loop를 실행하떄마다 2번씩 server호출을 하게 된다.
2번처럼 호출을 해야한다. client쪽에서 PreparedStatement 객체를 지우지말고 재활용해야한다.
PreparedStatement vs ConnectionPool
- MySQL 서버의 PreparedStatement는
- 하나의 Connection 내에서만 공유된다.
- re-parsing 비용을 최소화한다.
- 모든 PreparedStatement는 Connection 단위로 캐시되어야 한다.
- 전체 커넥션이 5000개이고 , 필요한 쿼리 패턴이 100개인 경우에는 500,000개의 PS객체가 MySQL 서버에 저장되어야 한다. (max_prepared_stmt_count = 16382)
- 쿼리의 복잡도에 따라서
- 매우 복잡하면 PreparedStatement가 도움이 된다.
- 단순하면 PreparedStatement의 장점이 경감된다.
- 메모리 사용량 vs cpu 사용량
- aws rds는 매우 소규모 서버들을 사용한다. (db.t3.medium & db.r5.large)
- 일반적으로 메모리 가 적은 경우가 많다.
- preparedstatement를 잘 생각해서 써야 할 것이다.
MySQL 서버에서는
- Server side PreparedStatement가 부작용이 심한 경우가 많다.
- client side PreparedStatement는 권장한다. (driver에서 sql injection만 방어하는듯)
Server side PreparedStatement가
- 예상하는 것처럼 성능을 크게 높여주진 않는다.
- 반면 메모리를 꽤 많이 소비하게 된다.(가끔 OOM을 유발한다)
- max_prepared_stmt_count 부족시, 쿼리 파싱 경감 효과가 떨어진다.
Distinct 는 함수가 아니며 괄호와 함께 사용한다고 하더라도 그렇지 않은 경우와 결과가 동일하다
괄호 사용시 오해의 여지가 있으므로 괄호 없는 형태로 사용하는 것을 권장한다.
위 예시의 결과들은 동일하다
order by 절 없이 limit n, m 문법 사용을 지양해야한다.
- 쿼리에서 order by 절 없이 limit이 사용되는 경우 어떤 의도로 작성된 건지 파악이 어렵다.
- 불필요한 limit이라면 제거하거나, 만약 페이지네이션 처리를 위한 것이라면 반드시 order by 절을 명시해서 사용해야한다.
- 4 ep 를 참고하자
group을 사용하는 경우 Full Group by 형태로 사용하는 것이 좋다
- select .. group by 쿼리에서 group by절에 명시되지 않은 컬럼을 select절에서 참조하는 경우 의도에 맞게 집계 함수를 반드시 사용하는 게 좋다
- 또는 불필요한 컬럼인 경우에는 제거하는것이 좋다.
- 어떤 값이 반환이 되더라도 상관이 없는 경우라면 랜덤 값을 return하는 ANY_VALUE()를 사용하는게
단순히 컬럼만 명시하는 것보다 낫다
And / Or 조건 함께 사용시 반드시 괄호 명시
- SQL에서 AND연산자는 OR연산자 보다 우선순위가 높아서, 괄호가 없는 경우 AND 연산자를 우선해서 처리한다.
- 가독성을 위해 AND/OR 조건을 쿼리에서 함께 사용하는 경우, 의도에 맞게 괄호를 반드시 명시해서 사용해야한다.
728x90
'Database > Real MySQL Season1 ,2' 카테고리의 다른 글
14) UUID 사용 주의사항 (0) | 2024.10.10 |
---|---|
13) 콜레이션 (0) | 2024.10.08 |
9) Error Handling , 10) Left Join 주의사항 및 튜닝 (0) | 2024.10.03 |
8) Generated 컬럼 및 함수 기반 인덱스 (0) | 2024.09.25 |
7) select for update (0) | 2024.09.24 |