데이터베이스 정규화와 스키마 투명성을 선호합니까?


10

새로운 요구 사항이 이전 코드베이스에 나타났습니다.이 코드는 기본적으로 이전에 관련이 없었던 두 사용자 클래스 사이의 기본적으로 (내부) 통신을 가능하게합니다 (완전히 다른 스키마를 가진 다른 테이블에 저장 됨) 덜 디자인되었으므로 부모 클래스가 없습니다). 우리는이 기능을 고려하지 않은이 오래된 설정에 봉착하기 때문에 사용중인 데이터 세트를 고려할 때 PK 충돌이 없다고 보장 할 수는 없습니다. 실제로 보장됩니다.

따라서 해결책은 분명해 보입니다. 화재로 죽이고 전체 엉망인 매핑 테이블을 다시 작성하십시오 . 나는지도를 구현하는 가능한 방법에 대해 두 가지 방향을 얻었지만 DBA는 아니므로 놓친 장단점이 있는지 확실하지 않습니다.

추상화를 명확하게하기 위해 교수, 관리, 학생의 세 가지 개별 사용자 데이터 그룹을 고려하십시오 (아니오, 이것은 숙제 과제가 아닙니다. 약속합니다!).

매핑 1

(professor_id, admin_id 및 student_id는 해당 테이블의 외래 키입니다)

| mailing_id (KEY) | professor_id | admin_id | student_id | 
-------------------------------------------------------
| 1001             |     NULL     |    87    |  NULL      |
| 1002             |     123      |   NULL   |  NULL      |
| 1003             |     NULL     |   NULL   |  123       |

이 접근법에 대한 +/-는 단점에 꽤 무거워 보입니다.

  • 행당 2 개의 "폐기물"필드
  • 2NF 위반
  • 예외 삽입 / 업데이트 취약점 (예 : 0-1 필드 만 NULL로 설정된 행)

그러나 전문가들은 자신의 장점이 없습니다.

  • 단일 조회로 매핑을 수행 할 수 있습니다
  • mailing_id에서 특정 사용자의 "소스"데이터를 쉽게 결정

진실은 내 직감에서 나는이 아이디어를 전혀 좋아하지 않는다는 것입니다.

매핑 2

(MSG_ *가 상수, 열거 형 또는 다른 적절한 식별자로 정의되어 있다고 가정)

| mailing_id (KEY)  | user_type (UNIQUE1) | internal_id (UNIQUE2)| 
------------------------------------------------------------------
| 1001              | MSG_ADMIN          | 87                    |
| 1002              | MSG_PROF           | 123                   |
| 1003              | MSG_STUDENT        | 123                   |

이 설정과 {user_type, internal_id}의 고유 한 복합 인덱스는 훨씬 깔끔 해지고 3NF는 유지되며 응용 프로그램 코드는 I / U 이상을 확인할 필요가 없습니다.

단점은 DB 외부에서 처리해야하는 사용자 소스 테이블을 결정하는 데있어 약간의 투명성 손실이 있으며, 기본적으로 user_type 값을 테이블에 응용 프로그램 수준으로 매핑합니다. 지금은 단점이 적기 때문에이 두 번째 매핑에 기울고 있습니다.

그러나 나는 내 자신의 한계를 고통스럽게 알고 있으며 아마도 두 가지 방향에서 장점이나 장애물을 놓쳤을 것이라고 확신하므로 내 것보다 더 현명한 마음으로 향합니다.


2
당신은 찾을 수있는 역할에 대한 마틴 파울러의 생각 재미있는 읽기.
Marjan Venema

실제로 흥미로웠다. 슬프게도 내 특정 문제에 대한 너무 많은 통찰력
GeminiDomino

관리자가 된 교수 및 행정직을 구하거나 10 년 후에 교수로 재학하는 학생들을 얻게됩니다. 아마 이미 가지고있을 것입니다. 그것들을 따로 보관하거나 통일하려고합니까?
Elin

역할은 단지 예일 뿐이지 만 요점을 알 수 있습니다. 실제로 사용자가 역할을 전환하더라도 어쨌든 별도의 레코드로 유지됩니다.
GeminiDomino

첫 번째 단락을 다시 말하면 좋을 것입니다. 조금 불분명하다. 내 말은, 문제가 있다는 것은 명백하지만 그것이 무엇인지 충분히 명확하지는 않습니다.
Tulains Córdova

답변:


1

두 번째 아이디어는 맞습니다. 이 방법을 사용하면 3 개의 충돌 키 공간을 통합하기 위해 수행해야하는 모든 매핑을 수행 할 수 있습니다.

중요한 것은 데이터베이스가 선언적 제약 조건 을 사용하는 데 필요한 대부분의 일관성을 강제 할 수있게하는 것 입니다.

이미 원하는 것보다 많은 코드가 있으므로 통합 키 목록의 일관성을 유지하는 데 꼭 필요한 것보다 더 많은 코드를 추가하지 마십시오. 데이터베이스 엔진이 수행 한 작업을 수행하게하십시오.

당신에게 불편을주고있다 "문제아" 매핑 2 는 IS USER_TYPE열입니다. 이 열은 INTERNAL_ID사용자 유형 당 최대 한 번만 표시 되도록하기 때문에 중요 합니다. 알고있는 코드가 필요한 유일한 시간 USER_TYPE은 매핑 테이블에서 삽입하고 삭제하는 코드입니다. 이것은 꽤 잘 현지화 될 수 있습니다. 코드에서 매핑 테이블 내용이 유지되는 단일 지점을 생성한다고 가정합니다. 이 한 곳에 데이터가 기록 되는 추가 열은 큰 문제가 아닙니다. 당신이 정말로 피하고 싶은 것은 데이터를 읽을 때마다 여분의 열을 추가하는 것 입니다.

매핑을 사용해야하는 하위 응용 프로그램의 코드는 USER_TYPE각 하위 응용 프로그램에 하나의 응용 프로그램 별 사용자 유형으로 매핑을 필터링하는보기를 제공함으로써 간단히 무시할 수 있습니다 .


3

경험을 바탕으로 우아함 또는 '모범 사례'보다 일관성을 선택하는 것이 좋습니다. 즉, 기존 디자인과 일치하고 간단한 mailing_id, user_id필드 구조를 가진 3 개의 메일 링 테이블 (각 역할에 대해 하나씩)로 이동합니다 .

우아하지 않지만 몇 가지 장점이 있습니다 ...

  1. 목초지에 넣기 전에이 스키마를 다루는 다른 사람들은 기존 구조를보다 쉽게 ​​일치시킬 수 있습니다.
  2. 당신은 필드를 낭비하지 않고 존재하지 않는 것들과 일치하도록 db를 요구하지 않습니다.
  3. 각 테이블은 서로간에 만 연결되므로 루틴에서 사용할 모든 데이터를 묶는보기를 비교적 쉽게 수행 할 수 있습니다.

많은 사람들이이 접근 방식에 동의하지 않을 것이라고 확신하지만 정규화 및 모범 사례의 주요 목표는 코드를보다 일관성있게 만들어 추적하고 디버깅하기가 더 쉬워야한다는 것입니다. 분명히 전체 코드베이스를 처음부터 다시 시작하는 것은 불가능할 것입니다.


이 접근 방식의 문제점은 데이터베이스가 메일 링 ID에 고유성을 적용 할 수 없다는 것입니다. 이는 메일 링 ID를 우선적으로 맵핑하는 주요 목적입니다. 그렇지 않으면 각 테이블의 개별 ID 필드를 "사용자 유형"표시기와 쌍을 이룰 수 있습니다. 아무런 변화없이 완료되었습니다.
GeminiDomino

나는 당신이 얻는 것을 보았지만 그런 종류의 시스템에서 일한 것은 당신이 고려하지 않은 옵션을 제공했습니다. 내가 아는 한 메일 링 ID는 어딘가를 참조하기 위해 어떤 내용이 필요합니다 (메일로 보낸 내용 또는 문서를 찾는 방법) 어쨌든 메일 링 ID는 외래 키 여야합니다. 즉, 고유성 문제는 다른 곳에서 해결 될 것입니다. 읽을 때 관리자 학생과 교수 데이터 테이블은 다른 구조를 가질 수 있으므로 사용자 유형 필드에 값이 추가되는 것을 볼 수 없습니다. 원래 개발자는이 문제에 부딪 쳤어 야했는데 어떻게 했습니까?
제임스 스넬

"사용자 유형"필드는 특정 레코드와 연관시킬 테이블을 결정합니다. 응용 프로그램 수준에서 어느 쪽이든 처리해야하며 다른 테이블에 있기 때문에 외래 키 제약 조건으로 만드는 좋은 방법은 없습니다. 원래 개발자는 불행히도이 문제를 전혀 고려하지 않은 것 같습니다. 그래서 그것이 엉망이되는 이유입니다. :)
GeminiDomino
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.