이것이 DB 스키마를 구성하는 어리석은 방법입니까, 아니면 완전히 빠진 것이 있습니까?


61

관계형 데이터베이스에 대해 약간의 작업을 해왔으며 좋은 스키마 디자인의 기본 개념을 잘 이해하고 있다고 생각합니다. 저는 최근에 고임금 컨설턴트가 DB를 설계 한 프로젝트를 맡았습니다. 내 직감이 본능인지 알려주세요- "WTF ??!?" -보증을 받습니까, 아니면이 사람이 저의 영역에서 운영되고있는 천재입니까?

문제의 DB는 직원의 요청을 입력하는 데 사용되는 사내 앱입니다. 작은 부분 만 살펴보면 사용자에 대한 정보와 요청에 대한 정보가 있습니다. 나는 이것을 이렇게 디자인 할 것이다.

사용자 테이블 :

UserID (primary Key, indexed, no dupes)
FirstName
LastName
Department

요청 테이블

RequestID (primary Key, indexed, no dupes)
<...> various data fields containing request details
UserID -- foreign key associated with User table

간단 하죠?

컨설턴트는 다음과 같이 설계했습니다 (샘플 데이터 사용).

Users 테이블

UserID  FirstName   LastName
234     John        Doe
516     Jane        Doe
123     Foo         Bar

부서 표

DepartmentID   Name
1              Sales
2              HR
3              IT

UserDepartmentTable

UserDepartmentID   UserID   Department
1                  234      2
2                  516      2
3                  123      1

요청 표

RequestID   UserID   <...>
1           516      blah
2           516      blah
3           234      blah

전체 데이터베이스는 이와 같이 구성되며 모든 데이터는 자체 테이블에 캡슐화되며 숫자 ID는 모든 것을 연결합니다. 컨설턴트는 OLAP에 대해 읽고 '정수 조회 속도'를 원했던 것 같습니다.

또한 이러한 모든 테이블을 상호 참조 할 수있는 많은 저장 프로 시저가 있습니다.

중소 규모의 SQL DB에 적합한 디자인입니까?

의견 / 답변 주셔서 감사합니다 ...


12
오 소년, 이것이 WTF라고하면 200 줄 이상의 테이블과 1000 줄 이상의 저장 프로 시저가없는 테이블을 보지 못했을 것입니다.
Job

42
당혹감을 느낀 후 삭제하지 않으면 +1 다른 사람들이 배울 수 있도록 이것을 남겨 주셔서 감사합니다.
Wayne Koorts

2
@Job-실제로, 나는하지 않았다-나는 무역에 의해 DBA가 아니다 (지금은 명백하다! lol), 내 SQL WTF 임계 값은 상당히 낮다. 컨설턴트 디자인의 요점을 완전히 잃어 버렸지 만 내 능력을 WTF에 빠뜨렸다. 멍청한 하루를 보낸 적이 있습니까?

9
@Jim : 축하합니다. 멍청한 하루를 깨달은 날로 바 꾸었 습니다.
Wayne Koorts

3
고액의 컨설턴트를 저주하십시오!
davidsleeps

답변:


73

나에게 완벽하게 이해됩니다. 그것은 매우 표준화되어있어 다른 유연성을 제공합니다. 비정규 화 된 데이터는 엉덩이에 통증이 있습니다.


귀하의 답변은 완벽하게 이해되며 내 질문과 스키마를 살펴보면 그가 사용하고있는 테이블의 수에 불과합니다. 나는 내 질문에 대한 예를 크게 단순화했지만 개념이 어떻게 건전한 지 알았습니다. 한숨, 나는 그것이 DBA가 아닌 좋은 일이라고 생각합니다! :)
Jim

10 분 규칙에 따라 디자인하는 법을 배우십시오. "현재 적용되는 것은 아마도 10 분 안에되지 않을 것입니다." 디자인이 변화를 다룰 수 있는지 확인하십시오.
Blrfl

1
이 스키마는 실제로 직원을 삽입 할 때 부서가 있어야한다는 이점이 있습니다.
Simon Richter

@SimonRichter : 사실이 아닙니다. 직원은 부서가 없어도 만들 수 있으며 그 반대도 가능합니다.
Daniel Dinnyes

@SimonRichter이 디자인의 이점은 첫째, 부서가 별도의 실체이고 둘째로 부서와 직원간에 다 대다 관계가 있다는 점입니다. "일대일"(대리인이라고 할 수 없었습니다. 별도의 부서 실체가 아니기 때문에 관계라고 부름).
Daniel Dinnyes

48

나는 WTF가 보증되거나 그 사람이 미친 천재적인 종류의 디자인을하고 있다고 생각하지 않습니다. 그것은 표준 데이터베이스 정규화입니다.

부서 테이블의 이유는 부서를 별도의 테이블에 넣지 않으면 "판매", "판매", "판매원", "항해"및 "판매"부서의 사용자를 처리해야하기 때문입니다. 당신이 그것을 막기 위해 무언가를하지 않는 한. 그리고 여분의 테이블을 갖는 것이 내가하는 가장 좋은 방법입니다.

UserDepartment 테이블이 있어야하는지 여부는 더 힘든 결정입니다. 한편으로 모든 테이블 디자인과 로직이 사용자 당 하나의 부서를 가정하고 그 변경 사항을 수년간, 몇 년 동안 아무런 이유없이 추가 조인을 수행하는 것이 진정한 가능성이자 고통입니다.

개인적으로 UserDepartment 테이블이 과도하게 사용된다는 데 동의합니다. 그것이 포함되어 있더라도 시간이 지남에 따라 사람들은 부서 당 사용자가 하나만 있다고 가정하는 쿼리를 작성할 수 있으므로 두 세계에서 최악의 결과를 낳을 수 있습니다. 사용자 당 하나 이상의 부서가 한 번만 작동하면 코드가 작동하지 않습니다.

편집-다 대다 관계를 지원해야하는지 여부의 핵심 동인은 비즈니스 규칙이 분명한 경우입니다. 여러 부서의 사용자가 어떻게 작동하는지 잘 모를 경우 테이블을 추가 할 필요가 없습니다. 코드가 사용자가 여러 부서에있는 경우를 올바르게 처리 할 수 ​​없기 때문입니다.

만약을 대비하여 사용자 당 많은 부서를 허용했다고 상상해보십시오. 그런 다음 부서를 기반으로 커미션을 할당하기위한 비즈니스 규칙을 구현했습니다. 그런 다음 여러 부서가 허용되었습니다. 운 좋게도이를 고려하여 커미션 코드를 작성해야합니다. 불행하게도, 당신은 추가 모두에서 사용자를 위해 각 부서에서 수수료를. 경영진은 각 판매의 개인 역할을 기반으로하기를 원했습니다. 그래서 테이블을 미리 가지고있는 것이 얼마나 좋습니까? 전혀 필요하지 않은 "경우에 따라"가지고 있던 다른 테이블은 어떻습니까?

나중에 편집-컨설턴트가 이러한 중간 테이블을 모두 추가하고 싶었던 또 다른 이유는 이 후속 질문 에서 다뤄 집니다 . 데이터베이스에 대한 리팩토링이 리팩토링 코드보다 어려운 이유를 제시하는 답변이 있습니다. "필요한 모든 테이블에 입력"접근 방식.


나는 당신이 내 WTF가 무엇인지 말로 표현한다고 생각합니다. 그 사람은이 정수 테이블의 TONS를 사용하고 있습니다. 이 질문에 대해 훨씬 작은 예제로 나누었으므로 나쁘지 않기 때문에 게시하는 것이 어리 석습니다.
Jim

5
많은 의견에서 알 수 있듯이 "Y 당 하나의 X 만있을 것"에 대한 건전한 회의론이 있습니다. 컨설턴트는 "Y 당 하나의 X 만있을 수있는 방법"불만에서 자신을 다루고 있습니다. 그중 일부는 아마 올 것입니다. 그러나 그는 많은 조인이 있고 (너무 나쁘지는 않지만 더 어려워) 아직 존재하지 않는 (나쁜) 비즈니스 규칙에 맞아야하는 코드를 유지 관리 할 책임이 없습니다. "사용자가 왜 모든 것을 얻는가? 각 부서의 권한이있는 경우 각 권한 중 가장 낮은 권한을 가져야합니다. "
psr

@psr 오타가 있다고 생각합니다. "부서 당 한 명의 사용자 만 있다고 가정하는 쿼리"는 "사용자가 한 부서에만 있다고 가정하는 쿼리"가 아니어야합니까?
BiAiB

@ BiAiB-당신 말이 맞습니다.
psr

14

사용자 당 여러 부서가 필요한 경우이 디자인이 적합합니다. 그것에 대해 유일한 불만은이 UserDepartmentTable대리 키를 갖는 UserDepartmentID(단지 만들 필요하지 않습니다 UserIdDepartmentId복합 기본 키).

사용자가 단일 부서에만 속해있는 경우에는 설계가 의미가 있습니다 (부서 조회 테이블은 여전히 ​​좋은 것임).


18
... 사용자 당 하나 이상의 부서가 가능할 때까지.
Blrfl

1
정확히 @Blrfl. 오늘의 결코 일어나지 않는 일이 내일의 CEO입니다. 왜냐하면 동맥류이기 때문입니다.
Adam Crossland

2
그러한 종류의 치료에 적합한 것을 결정하는 것의 일부는 문제 영역을 이해하는 것입니다. 일부 응용 프로그램에서는 직원 # 3804가 회사에 Ann Smith 및 Ann Jones (결혼 후)로 알려져있어 직원 테이블에서 이름을 정상화하는 것이 제정신임을 아는 것이 중요합니다. Jim의 경우 Ann이 HR에서 IT로 이동하는 경우 Ann이 HR에 연결된 오래된 요청이 IT의 요청이 아니라 실제로 HR의 요청임을 반영 할 수 있도록 차단기 테이블을 확장하는 것이 좋습니다.
Blrfl

8
YAGNI-데이터베이스를 리팩토링 할 수 있습니다.
JeffO

2
@Oded, Entity Framework와 같은 일부 ORM 맵퍼는 복합 기본 키가있는 테이블에서 제대로 작동하지 않습니다.
maple_shaft

5

귀하의 질문에 일부 요구 사항이 명확하지 않습니다. 정답은 고객이 원하는 것에 따라 다릅니다. 본인 인 경우 고객에게 다음과 같이 문의합니다.

0- 사용자와 직원의 차이점은 무엇입니까?

1- 직원 = 사용자라고 가정하면 직원이 부서를 변경하면 어떻게됩니까?

2- 직원 그룹이 1 개의 요청을 할 수 있습니까?

3- 직원이 둘 이상의 부서에 속할 수 있습니까? CEO는 어떻습니까

4- 요청을 할 수있는 직원이 있습니까?

5- 직원 레코드가 삭제되면 요청은 어떻게됩니까?

6- 요청을 삭제할 수 있습니까? 요청이 삭제되면 어떻게됩니까 (RI로 직원 레코드를 삭제하지 않아야 함)

7- 직원이 "동일한"요청을 두 번 이상 할 수 있습니까 ( "동일한"정의)

8- 직원이 회사를 떠날 때 요청을 처리하는 방법 (요청을 취소하거나 삭제 하시겠습니까?)

더 많은 질문이있을 수 있지만, 요점은 솔루션이 정확한 요구 사항과 프로젝트 범위 에 달려 있다는 것 입니다. 일단 결정되면 스키마를 직접 파생시킬 수 있습니다. 따라서 제시된 두 가지 솔루션이 모두 정확할 수 있습니다.


+1 이러한 유형의 스키마를 설계하기 전에 명확히해야하는 훌륭한 질문입니다. 나는 당신의 논리의 흐름을 좋아합니다.

@ Surfer513 : 좋은 의견 주셔서 감사합니다.
NoChance

1

고액의 컨설턴트가 수행 한 방식으로 조인 테이블을 사용할 때의 몇 가지 잠재적 이점에 대해 명시 적으로 설명하는 몇 가지 포인트 양식 메모를 추가하고 싶습니다.

  • 올바르게 인덱스 화됨 (예 : UserDepartmentTable이 두 개의 외래 키를 색인화하는 경우) 외래 키가 고유하지 않기 때문에 이와 같은 조인 테이블의 성능이 약간만 저하됩니다. 외래 키가 고유하다는 것을 보증하는 경우, 내가 아는 작은 데이터베이스 이론에 따르면 조회 UserDepartmentTable.DepartmentUser테이블의 다른 열을 찾는 것보다 "더 어렵지 않습니다" .
  • 조인 테이블을 사용하면 사용자와 부서 간의 연결에 대한 다른 정보 (예 : 생성시 타임 스탬프)를보다 유연하게 설정할 수 있습니다.
  • 결합 테이블을 사용하면 연관을 상당히 쉽게 "버전 화"할 수 있습니다 (예를 들어, 사용자가 부서를 변경하면 일부 부울 플래그 UserDepartmentTable.Active를 false로 트리거하고 활성화 된 새 연관을 작성 함). 두 테이블 모델 (사용자 및 부서 만)을 사용하여 부서 연관 버전 화를 수행 할 수도 있지만 기본 키가 중복되는 것을 피하기 위해 하나 이상의 열을 추가하거나 데이터베이스 곡예를 수행하는 것이 더 어렵고 필요합니다.
  • 일대 다 또는 다 대일 또는 다 대다 연관을 매우 쉽게 지정할 수 있습니다.

즉, 고액의 컨설턴트가 한 일을하지 말아야 할 몇 가지 이유가 있습니다.

  • 위의 모든 혜택 은 가능한 미래의 요구를 예상하여 현재의 일을 지나치게 복잡하게 만듭니다. YAGNI 호환이 아닙니다. 나중에 2 테이블 모델에서 조인 테이블 모델로 이동하는 마이그레이션을 작성하는 것은 쉽지 않습니다. 비즈니스 요구가 발생할 때 그렇게 할 수 있습니다. 그 전에 혼란 스러울 수 있습니다.
  • 다른 개발자들을 혼란스럽게합니다. 네, 웹 컨설턴트 (컨설턴트의 결정을 검토하는 곳)에 대한 기대는 조인 테이블을 이해하고 인식하는 것이지만, 비즈니스 요구의 부족을 고려할 때 여전히 필요한 것보다 더 복잡합니다. 혼란을 야기합니다.

멋진 분석-그러나 나는 db / c # / vb / etc에 대해 아무것도 알고있는 유일한 사람이라는 것을 제외하고는 하루 종일 개발자로 키가 없다고 말하지 않을 것입니다. 기본적으로 시간 dev. 이것은 상당히 작은 프로젝트이기 때문에 컨설턴트들은 테이블의 수와 조인을 통해 "wtf"라고 말하게되었습니다 (그러나 여러분 덕분에 저는 "oic ..."이라고 말하고 있습니다)
Jim

꽤 오래된 주제이지만 여전히 관련성이 있습니다 ... 리팩토링은 매우 어려울 수 있습니다. 나중에 하나 대신 여러 부서가 필요하지만 사용자에는 부서 ID 만 FK로 가정합니다. 중복 된 참조 (Users.DeptID 및 UsersDepartmentsTable) 또는 완전한 가비지 (예 : Users.DeptID 또는 XML의 쉼표로 구분 된 목록)로 끝날 수 있습니다. YAGNI 또는 KISS가 제안한대로 올바른 솔루션을 쉽게 추가 할 수는 없었지만 방해가되었습니다.
Erik Hart

0

필요한 정보의 전체 구조가 없으면 끔찍한 지 말할 수 없습니다. 그러나 적어도 보여지는 부분은 "WTF"디자인이 아닙니다. 데이터 구조의 3 차 정규 형식 인 것 같습니다 (물론 이론적으로 4 차 및 5 차도 있습니다)

두 조각의 "자연"키와 "인공"키 사이에 UserDepartmentTable에 대한 대화가있을 수 있습니다. 내가 볼 수 있듯이 더 이상

정규화가 많은 이유에 대한 좋은 DB-개발자 / 디자이너의 규칙입니다, * * 정상화 속도 - 윈 대부분을위한 개발의 중간에 종종 사용된다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.