사용자 도구

사이트 도구


database:sqlantipatterns

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판 이전 판
다음 판
이전 판
다음 판 양쪽 다음 판
database:sqlantipatterns [2011/10/21 17:23]
kwon37xi [가상키 편집증]
database:sqlantipatterns [2016/09/24 15:14]
kwon37xi
줄 15: 줄 15:
  
 ===== 순진한 트리 ===== ===== 순진한 트리 =====
-  * 목표 : 재귀적 관계를 갖는데이터를 트리나 계층적 구조로 만든다.+  * 목표 : 재귀적 관계를 갖는 데이터를 트리나 계층적 구조로 만든다.
   * 안티패턴 : parent_id 칼럼을 추가하라.   * 안티패턴 : parent_id 칼럼을 추가하라.
-  * 해법 : 다른 트리 모델을 사용하라.(생략)+  * 해법 : 다른 트리 모델을 사용하라.
   * Tip : 계층 구조에는 항목과 관계가 있다. 작업에 맞도록 이 둘을 모두 모델링해야 한다.   * Tip : 계층 구조에는 항목과 관계가 있다. 작업에 맞도록 이 둘을 모두 모델링해야 한다.
  
줄 30: 줄 30:
  
 ===== 키가 없는 엔트리 ===== ===== 키가 없는 엔트리 =====
-  * 목표 : 데이터베이스 아키텍를 단순화하고 싶다.+  * 목표 : 데이터베이스 아키텍를 단순화하고 싶다.
   * 안티패턴 : FK 제약조건 생략.   * 안티패턴 : FK 제약조건 생략.
     * 이 경우 참조 정합성을 보정하는 코드를 직접 작성하는 책임을 져야 한다.     * 이 경우 참조 정합성을 보정하는 코드를 직접 작성하는 책임을 져야 한다.
줄 36: 줄 36:
   * 해법 : 참조 정합성을 강제하는 FK를 사용하라. 데이터 정합성 오류를 찾아내 정정하는 대신, 처음부터 잘못된 데이터가 입력되지 않도록 하라.   * 해법 : 참조 정합성을 강제하는 FK를 사용하라. 데이터 정합성 오류를 찾아내 정정하는 대신, 처음부터 잘못된 데이터가 입력되지 않도록 하라.
   * Tip : 제약조건을 사용해 데이터베이스에서 실수를 방지하라.   * Tip : 제약조건을 사용해 데이터베이스에서 실수를 방지하라.
- 
 ===== 엔티티-속성-값 ===== ===== 엔티티-속성-값 =====
   * 목표 : 가변 속성 지원(보통 엔티티의 상속 구조를 표현할 때 이런 경우가 발생한다)   * 목표 : 가변 속성 지원(보통 엔티티의 상속 구조를 표현할 때 이런 경우가 발생한다)
줄 59: 줄 58:
       * 모든 서브타입에 대한 조회가 많고 공통 칼럼을 참조하는 경우가 많을 때 적합하다.       * 모든 서브타입에 대한 조회가 많고 공통 칼럼을 참조하는 경우가 많을 때 적합하다.
     * 반구조적 데이터(Semistructured Data)     * 반구조적 데이터(Semistructured Data)
-      * 단일 테이블 상속과 유사하지만 서브타입의 송석을 칼럼으로 저장하지 않는다.+      * 단일 테이블 상속과 유사하지만 서브타입의 속성을 칼럼으로 저장하지 않는다.
       * 데이터의 속성 이름과 값을 XML또는 JSON 형식으로 부호화해 TEXT혹은 CLOB 칼럼으로 저장.       * 데이터의 속성 이름과 값을 XML또는 JSON 형식으로 부호화해 TEXT혹은 CLOB 칼럼으로 저장.
       * 서브타입의 개수를 제한할 수 없고, 어느 때고 새로운 속성을 정의 할 수 있는 완전한 유연성이 필요할 때 적합하다.       * 서브타입의 개수를 제한할 수 없고, 어느 때고 새로운 속성을 정의 할 수 있는 완전한 유연성이 필요할 때 적합하다.
줄 124: 줄 123:
     * NUMERIC과 DECIMAL은 유리수가 반올림되지 않고 저장된다.     * NUMERIC과 DECIMAL은 유리수가 반올림되지 않고 저장된다.
   * Tip : 가능하면 FLOAT을 사용하지 말라.   * Tip : 가능하면 FLOAT을 사용하지 말라.
 +  * Precision and scale : http://sqlrelay.sourceforge.net/sqlrelay/programming/precisionscale.html
 +    * precision 정밀도 : 소수점 앞뒤를 모두 포함한 총 자리수
 +    * scale : 소수점 뒤 자리수
 +    * 예) 112.34 : precision 5, scale 2
  
 ===== 31가지 맛 ===== ===== 31가지 맛 =====
줄 169: 줄 172:
     * IS NULL/IS NOT NULL/IS DISTINCT FROM(피연산자가 NULL이더라도 true/false리턴, MySQL에서는 ''<=>'')     * IS NULL/IS NOT NULL/IS DISTINCT FROM(피연산자가 NULL이더라도 true/false리턴, MySQL에서는 ''<=>'')
     * 어떤 칼럼이 논리적인 디폴트 값을 가지지 않더라도 NOT NULL 제약조건이 필요한 경우는 정당하고 흔하다.     * 어떤 칼럼이 논리적인 디폴트 값을 가지지 않더라도 NOT NULL 제약조건이 필요한 경우는 정당하고 흔하다.
-    * COALESCE() 함ㅜ : 가변인수를 받아서 NULL이 아닌 첫 인수 리턴+    * [[http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce|COALESCE()]] 수 : 가변인수를 받아서 NULL이 아닌 첫 인수 리턴
   * Tip : 어떤 데이터 타입에 대해서든 누락된 값을 뜻하는 데는 NULL을 사용하라.   * Tip : 어떤 데이터 타입에 대해서든 누락된 값을 뜻하는 데는 NULL을 사용하라.
  
줄 255: 줄 258:
   * Tip : 가상키를 행의 식별자로 사용한다. 가상키는 행 번호가 아니다.   * Tip : 가상키를 행의 식별자로 사용한다. 가상키는 행 번호가 아니다.
 ===== 나쁜 것 안 보기 ===== ===== 나쁜 것 안 보기 =====
 +  * 목표 : 코드를 적게 작성하기
 +  * 안티패턴 : 데이터베이스 API 리턴 값 무시하는 코드. 애플리케이션 코드에 산재해 있는 SQL 코드의 단편만 보기
 +  * 안티 패턴 사용이 합당한 경우 : 객체지향언어에서 문제 발생시 예외를 던지므로 모든 문장에 대해 에러 여부를 고민하지 않아도 된다.(PHP 등의 일부 언어는 에러가 발생하면 예외를 던지지 않고 리턴 값에 예외 코드를 넣기 때문에 각각의 문장 실행후 예외 코드를 검사해야 하는 것으로 보임).
 +  * 해법 : 
 +    * 에러 검사 코드 작성
 +    * 애플리케이션 코드에 중간중간 있는 SQL말고 실제 실행된 SQL 코드 확인
 +  * Tip : 코드의 문제를 해결하는 것만으로도 이미 충분히 어렵다. 보지 않고 작업해 스스로를 방해하지 말라.
 ===== 외교적 면책특권 ===== ===== 외교적 면책특권 =====
 +  * 목표 : 프로그램 개발의 관례 따르기. 대부분의 노련한 개발자들은 편의를 위해 이런 관례를 희생하는 것이 실패의 지름길임을 안다.
 +  * 안티패턴 : SQL은 프로그램이 아니라고 생각하고 일반적인 관례를 따르지 않는 경우.
 +  * 안티 패턴 사용이 합당한 경우 : 한 번 사용하고 바로 삭제해도 되는 임시 SQL를 만들 경우
 +  * 해법 : 초당적 품질 문화 확립. SQL도 일반적인 프로그래밍의 관례인 문서화, 버전관리, 자동화된 테스틀 하라.
 +    * [[http://blog.stackoverflow.com/2010/01/podcast-80/|Jeff Atwood와 Joel Spolsky는 StackOverflow 팟캐스트 #80에서 코드에 대한 문서화는 가치가 거의 없다고 본다. 데이터베이스는 제외하고 말이다.]]
 +  * Tip : 애플리케이션뿐만 아니라 데이터베이스에 대해서도 문서화, 테스트, 소스 코드 관리와 같은 소프트웨어 개발 관례를 사용하라.
 ===== 마법의 콩 ===== ===== 마법의 콩 =====
 +  * 목표 : MVC에서 모델 단순화하기
 +  * 안티패턴 : MVC 애플리케션에서 모든 모델 클래스가 액티브 레코드(ActiveRecord) 클래스를 상속하는 관행
 +  * 안티 패턴 사용이 합당한 경우 : 프로토타이핑
 +  * 해법 : 액티브 레코드를 가지는 모델
 +    * 모델과 액티브 레코드와 같은 DAO 사이의 관계는 IS-A(상속)가 아닌 HAS-A(집합연관)여야 한다. 액티브레코드를 사용하는 대부분의 프레임워크는 IS-A 관계를 가정한다.
 +  * Tip : 테이블에서 모델을 분리하라.
 +
 +이 항목은 따로 설명하면, 액티브 레코드가 나쁘다는 얘기가 아니다.
 +
 +컨트롤러에서 DAO 혹은 액티브 레코드의 DB관련 메소드(혹은 그 외의 데이터 접근에 직접 관련된 메소드)를 직접 호출하지 말라는 얘기이다.
 +Java로 설명하면 Controller는 Service를 호출하고 Service에서 DAO를 호출해야 한다. Controller에서 DAO를 직접 호출되면 안된다.
 +이 원칙을 액티브 레코드를 사용하는 MVC 프레임워크에서도 그대로 적용하며 Controller에서 ActiveRecord의 데이버테이스 접근 메소드를 직접 호출하지 말고 중간 모델 객체(서비스 객체)를 두라는 의미이다.
 +
 +--
 +그 외..
 +
 +===== EXIST()를 사용할 곳에 COUNT() 사용금지 =====
 +  * [[https://blog.jooq.org/2016/09/14/avoid-using-count-in-sql-when-you-could-use-exists/|Avoid Using COUNT() in SQL When You Could Use EXISTS()]]
  
database/sqlantipatterns.txt · 마지막으로 수정됨: 2016/09/24 15:16 저자 kwon37xi