Database/Real MySQL Season1 ,2

11) Prepared Statement , 12) SQL 문장의 가독성 향상

Tony Lim 2024. 10. 7. 14:06
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