2012-03-29 29 views
7

Tôi thường thấy mình đang đặt câu hỏi liệu mình có đang sử dụng đúng cách để cố gắng lên kế hoạch mở rộng trong tương lai khi tạo cơ sở dữ liệu và quan hệ hay không.Tại điểm nào, việc chuẩn hóa dữ liệu trở nên lố bịch?

Tôi có tình huống sau đây:

  1. Tôi có một bảng Donor và một bảng Recipient. Cả hai bảng chia sẻ thông tin phổ biến như first_name, last_name, email_address, date_of_birth, v.v. Cả hai dường như, nếu bạn sẽ tha thứ ngôn ngữ hướng đối tượng của tôi, hãy chia sẻ một loại trừu tượng chung là Person. Có thể người nào đó ở một thời điểm là Recipient sau này có thể trở thành Donor bằng cách tặng tiền, vì vậy điều quan trọng là thông tin không được sao chép trên các bảng. Tôi có nên chọn kiểu mẫu thừa kế hay tôi chỉ cần nhập khóa ngoài Donor s và Recipient s vào bảng Person? Ban đầu, tôi đã nghĩ đến việc đơn giản hóa các thuộc tính như email_address và các thuộc tính địa chỉ đường phố trực tiếp vào những thứ cần chúng, nhưng khả năng có thể xảy ra là một người sẽ có nhiều địa chỉ email hoặc địa chỉ gửi thư (ví dụ: nhà riêng, công việc, v.v.) Điều đó có nghĩa là chúng tôi có một mô hình hơi giống như thế này:

    create table person(id int primary key auto increment, ..., 
        default_email_address); 
    
    create table email_address(id int primary key auto increment, 
        email varchar(255), name varchar(255), is_default bool, person_id int); 
    

    Điều này làm cho mọi thứ trở nên phức tạp, như bạn có thể tưởng tượng. Trường name cũng bao gồm danh sách các giá trị mặc định cũng như cho phép nhập tùy chỉnh. Tôi không thể chỉ là một lĩnh vực enum, bởi vì khả năng tồn tại là ai đó sẽ có rất nhiều email để thêm rằng tất cả có thể khác nhau ... (đây là điểm mà tôi hét lên "IS IT EVEN WORTH IT ANYMORE !?!? "và cảm thấy thất vọng với dự án)

Tôi đoán điều này thực sự nhấn mạnh như sau: tại điểm nào bình thường hóa dữ liệu trở nên lố bịch? Mục tiêu của tôi ở đây là tạo ra một mô hình dữ liệu tương thích với khả năng tương thích tốt mà tôi sẽ không tự tạo ra sau này.

+0

Trong # của bạn 2, những gì sẽ là sự thay thế cho bình thường hóa dữ liệu? Bạn gần như chắc chắn không muốn nhiều giá trị cho một trường duy nhất trong một hàng, vì vậy tôi không thấy một thay thế nào để tách ra thành một bảng khác. –

Trả lời

7

tại điểm nào việc chuẩn hóa dữ liệu trở nên lố bịch?

Tại thời điểm dừng mô hình hóa các yêu cầu thực tế.

Chịu ví dụ của bạn:

  • Với các bảng DonorRecipient, nếu nó là rất có khả năng rằng bất kỳ một người sẽ trở thành cả hai, sau đó nó làm cho tinh thần để tách ra một thực thể Person. Nếu điều này là hiếm, nó không.

  • Với các tình huống email_addressstreet_address, điều đó phụ thuộc vào việc bạn có cần lưu trữ bội số hay không (kỳ vọng là gì?). Bạn có thể muốn lưu trữ các phiên bản riêng biệt cho mỗi đơn vị kinh doanh (giả sử shipping_address so với billing_address).

+1

+1 cho "khi dừng mô hình hóa các yêu cầu thực tế". Đi xa về mô hình hóa dữ liệu tương tự như đi xa khi xây dựng một cấu trúc lớp OO. –

+0

Vấn đề chính mà tôi đang cố gắng dự đoán là những thay đổi trong tương lai. Điều gì nếu khách hàng đến và nói với tôi rằng họ muốn có nhiều địa chỉ hoặc địa chỉ email? Cách tôi nhìn thấy nó, tôi hoặc là đối phó với vấn đề từ get-go, hoặc bị một di chuyển SQL sau đó. –

+2

@TKKocheran - Đó là vấn đề ngay tại đó: 'Tôi đang cố gắng dự đoán là những thay đổi trong tương lai'. Đừng. Xây dựng một hệ thống sạch sẽ hoạt động cho các yêu cầu _current_. Khi họ thay đổi, hãy thay đổi hệ thống. Bạn không thể thấy trước tương lai - chấp nhận điều đó. – Oded

3

Tôi nghĩ rằng vấn đề không nằm trong quá trình triển khai của bạn, mà đúng hơn là trong phân tích vấn đề của bạn.DonorRecipient không phải là diễn viên hạng nhất, họ là vai trò của các diễn viên. Nếu bạn mô hình chúng như vậy, bạn sẽ nhận được một mô hình hơi bụi:

  • Bạn muốn có một bảng người có địa chỉ và vân vân
  • Bạn cũng muốn có một bảng địa chỉ với địa chỉ của người dân
  • Bạn cũng sẽ có bảng person_role, với mã vai trò (nhà tài trợ, người nhận) và thông tin liên quan khác. Bạn có thể muốn được ưa thích và thêm person_donorperson_recipient, với khóa ngoài vào bảng person.
0

Tôi sẽ đặt tất cả dữ liệu được chia sẻ vào bảng Person. Các bảng DonorRecipient chỉ nên chứa dữ liệu cụ thể cho từng tab và phải có khóa ngoài trỏ về khóa chính của Person.

Đây không phải là chuẩn hóa lố bịch; nó thực sự khá phổ biến.

2

Câu trả lời ngắn: Bình thường hóa không bao giờ trở nên vô lý. Hầu hết những gì bạn đang làm không phải là bình thường hóa.

Còn trả lời

Các "tồi tệ nhất" (thực ra, "tốt nhất) hầu hết các nhà thiết kế thực tế có thể làm là kết thúc với tất cả các bảng trong 5NF. 5NF không phải là vô lý chút nào. (Vâng, tôi biết về 6NF. tôi bỏ qua nó vì lý do giáo khoa.)

đặt câu hỏi liệu tôi dùng phương pháp đúng trong việc cố gắng lên kế hoạch cho bành trướng tương lai

Th đó là một câu hỏi hay để tự hỏi bản thân. Nó không có gì để làm với bình thường, mặc dù. Ở cấp độ khái niệm, bình thường hóa là điều bạn làm sau bạn đã quyết định thuộc tính nào (cột) và dữ liệu cần phải đi vào cơ sở dữ liệu của bạn. Các nhà thiết kế cơ sở dữ liệu có kinh nghiệm thường "suy nghĩ trong 3NF", chọn thuộc tính, dữ liệu và chuẩn hóa tất cả cùng một lúc, nhiều hơn hoặc ít hơn.

Tôi có nên chọn kiểu thừa kế hay tôi chỉ cần nhập khóa ngoài Nhà tài trợ và người nhận vào bảng Person?

Nhà tài trợ và người nhận không phải là loại người khác nhau. Các nhà tài trợ là những người đã đóng góp. Người nhận là những người đã nhận được điều gì đó.

id fullname  don_date don_amt recip_date recip_amt 
-- 
1 Jamie Hubbert 2012-01-13 $20.00 
1 Jamie Hubbert 2012-02-13 $17.00 
2 Kelly Hawkin 2012-01-13 $50.00 
2 Kelly Hawkin 2012-01-13 $20.00 
3 Neva Papke       2012-01-13 $15.00 
3 Neva Papke       2012-02-13 $15.00 
2 Kelly Hawkin      2012-01-13 $10.00 
4 Jamie Hubbert 2012-01-13 $10.00 
4 Jamie Hubbert      2012-02-13 $10.00 

Trong quá trình chuẩn hóa, bạn sẽ xác định những phụ thuộc này. (Để đơn giản, giả định một khoản đóng góp cho mỗi người mỗi ngày.)

  • Person_Id -> PERSON_NAME
  • Person_Id -> email
  • Person_Id, donation_date -> donation_amount
  • Person_Id, recip_date -> recip_amount

Normalize để 5NF, và bạn muốn có được ba bảng này.

Persons 
-- 
1 Jamie Hubbert 
2 Kelly Hawkin 
3 Neva Papke 
4 Jamie Hubbert 

Donations 
-- 
1 2012-01-13 $20.00 
1 2012-02-13 $17.00 
2 2012-01-13 $50.00 
2 2012-01-13 $20.00 
4 2012-01-13 $10.00 

Receipts (?) 
-- 
3 2012-01-13 $15.00 
3 2012-02-13 $15.00 
2 2012-01-13 $10.00 
4 2012-02-13 $10.00 

Ban đầu, tôi đã nghĩ đến việc tính chỉ đơn giản là lập bản đồ như EMAIL_ADDRESS và địa chỉ đường phố thuộc tính trực tiếp vào những điều rằng cần đến chúng, nhưng sau đó các khả năng có thể xảy ra rằng một người sẽ có nhiều địa chỉ email hoặc địa chỉ gửi thư (ví dụ: nhà riêng, cơ quan, , v.v.).

Quyết định có hỗ trợ nhiều địa chỉ email, nhiều địa chỉ gửi thư và địa chỉ gửi thư và gửi thư khác nhau hay không là quyết định thiết kế quan trọng. Nhưng nó không liên quan gì tới việc bình thường hóa. Bình thường hóa, một lần nữa, là một cái gì đó bạn làm sau khi bạn đã quyết định thuộc tính và dữ liệu nào thuộc về cơ sở dữ liệu của bạn. Vì vậy, nếu bạn đang thu thập đại diện dữ liệu mẫu, bạn có thể kết thúc với một trong hai bộ địa chỉ email này.

Set A 
1 Jamie Hubbert [email protected] 
4 Jamie Hubbert [email protected] 

Set B 
1 Jamie Hubbert [email protected] 
1 Jamie Hubbert [email protected] 
4 Jamie Hubbert [email protected] 

Trong bộ A, person_id-> email. Trong tập B, nó không. Chọn hỗ trợ dữ liệu trong tập A hoặc dữ liệu trong tập B là quyết định lớn và ảnh hưởng mạnh mẽ đến những gì bạn kết thúc với sau khi bình thường hóa thành 5NF. Nhưng việc quyết định thiết lập để hỗ trợ không có gì để làm với bình thường.

Ngoài ra, việc chọn chỉ định số id cho các địa chỉ email không duy nhất là một quyết định thiết kế lớn (và đáng ngờ) khác. Giống như những người khác, quyết định này không liên quan gì đến việc bình thường hóa.

(tên Random kê biếu không của The Random Name generator.)

Các vấn đề liên quan