Tại sao mô hình quan hệ cho một cơ sở dữ liệu quan trọng?


61

Tôi đang tiếp cận một dự án mà tôi sẽ phải triển khai cơ sở dữ liệu với sếp của mình; chúng tôi là một khởi đầu rất nhỏ nên môi trường làm việc mang tính cá nhân sâu sắc.

Anh ấy đã đưa cho tôi một trong những cơ sở dữ liệu của công ty trước đây và nó hoàn toàn đi ngược lại những gì tôi được dạy (và đọc về) ở trường cho RDBMS. Ví dụ, có toàn bộ cơ sở dữ liệu ở đây bao gồm một bảng (trên mỗi cơ sở dữ liệu độc lập). Một trong những bảng đó dài hơn 20 cột và theo ngữ cảnh, đây là một số tên cột từ một bảng:

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngSản phẩm | tên sản phẩm

Vấn đề là ở chỗ anh ta nên có các bảng riêng lẻ chứa dữ liệu thực thể (tên, kích thước, ngày mua, v.v.), anh ta sẽ đẩy tất cả vào một bảng lớn trên mỗi cơ sở dữ liệu.

Tôi muốn cải thiện thiết kế này, nhưng tôi không chắc tại sao một mô hình dữ liệu được chuẩn hóa và phân đoạn đúng sẽ thực sự cải thiện sản phẩm này. Mặc dù tôi quen thuộc với thiết kế cơ sở dữ liệu từ trường đại học và tôi hiểu làm thế nào để làm điều đó, tôi không chắc tại sao điều này thực sự cải thiện cơ sở dữ liệu.

Tại sao một lược đồ quan hệ tốt cải thiện cơ sở dữ liệu?


33
Một từ: Bình thường hóa.
Robert Harvey

9
Đóng cử tri - biện minh cho chính mình! :-)
Robbie Dee

6
Thông thường các nhân viên mới chỉ trích các quy trình đã được thiết lập mà không hiểu lý do đằng sau chúng, ngay cả khi những lý do đó không đúng về mặt kỹ thuật. Trước tiên hãy tìm hiểu lý do tại sao ông chủ của bạn xây dựng nó theo cách đó. Anh ấy / cô ấy có thể biết rất rõ rằng đó không phải là một thiết kế tốt, nhưng không có kiến ​​thức (hoặc nhiều khả năng, thời gian) để làm nó tốt hơn. Bất kỳ thay đổi nào bạn đề xuất có thể sẽ được nhận tích cực hơn nếu bạn tôn trọng thừa nhận lý do cho thiết kế hiện tại.
Pedro

5
He [the boss] had given me one of his databases before and it completely went against what I was taught (and read about) in school for RDBMS<- Chào mừng đến với thế giới thực!
Möoz

5
Tôi nhớ lại câu trích dẫn cơ sở dữ liệu quan hệ yêu thích của tôi: "Bình thường hóa cho đến khi nó đau, không chuẩn hóa cho đến khi nó hoạt động"
Jake

Câu trả lời:


70

Đối số hiệu suất thường là đối số trực quan nhất. Bạn đặc biệt muốn chỉ ra làm thế nào để khó thêm các chỉ mục tốt vào cơ sở dữ liệu được chuẩn hóa không chính xác (lưu ý: có những trường hợp cạnh mà việc không chuẩn hóa trên thực tế có thể cải thiện hiệu suất, nhưng khi bạn không có kinh nghiệm với cơ sở dữ liệu quan hệ, bạn có thể sẽ không dễ dàng xem những trường hợp này)

Một cái khác là đối số kích thước lưu trữ. Một bảng không chuẩn hóa với nhiều dự phòng sẽ yêu cầu lưu trữ nhiều hơn. Điều này cũng đóng vai trò vào khía cạnh hiệu suất: bạn càng có nhiều dữ liệu, các truy vấn của bạn sẽ càng chậm.

Ngoài ra còn có một đối số khó hiểu hơn một chút, nhưng thực tế lại quan trọng hơn vì bạn không thể giải quyết nó bằng cách ném thêm phần cứng vào nó. Đó là vấn đề thống nhất dữ liệu. Một cơ sở dữ liệu được chuẩn hóa đúng sẽ tự bảo đảm rằng một sản phẩm có ID cụ thể luôn có cùng tên. Nhưng trong một cơ sở dữ liệu không chuẩn hóa, sự không nhất quán như vậy là có thể, vì vậy cần phải cẩn thận khi tránh sự không nhất quán, điều này sẽ làm mất thời gian lập trình để có được quyền và vẫn sẽ gây ra lỗi khiến bạn phải hài lòng.


19
Một trường hợp chính cho việc không chuẩn hóa là lưu trữ dữ liệu , cụ thể, nếu bạn có một lượng lớn dữ liệu được đảm bảo không bao giờ thay đổi và bạn muốn truy vấn nó nhanh hơn và hiệu quả hơn với chi phí không gian lưu trữ. Câu trả lời hay, đây chỉ là một FYI cho bất kỳ người mới sử dụng SQL nào, những người không chắc chắn tại sao mọi thứ khác ngoài 3NF sẽ được mong muốn.


11
Tôi không chắc tại sao đối số nhất quán lại "khó hiểu hơn". Nó có vẻ đơn giản hơn nhiều đối với tôi: nếu một giá trị thay đổi, thì tất cả các bản sao của giá trị đó phải được cập nhật. Cập nhật một bản sao ít bị lỗi hơn nhiều so với cập nhật hàng trăm hoặc hàng nghìn bản sao của cùng một dữ liệu. Điều này áp dụng tốt như nhau cho mối quan hệ giữa dữ liệu. (Nếu tôi có mối quan hệ được lưu trữ theo hai cách, tôi phải cập nhật cả hai bản sao của mối quan hệ.) Đây là một vấn đề cực kỳ phổ biến trong các DB không chuẩn hóa; đó là rất khó khăn để ngăn chặn tham nhũng này trong thực tế (một ngoại lệ được cụ thể hóa quan điểm sử dụng loại).
jpmc26

4
Đoạn cuối đó nên được tô đậm. :-) Nếu không được chuẩn hóa, không thể đảm bảo tính toàn vẹn dữ liệu. Chỉ kiểm soát đầu vào ở lớp Business Logic là một việc vặt vì mọi cơ sở dữ liệu không chuẩn hóa cuối cùng đều thể hiện một số loại dữ liệu bất thường.
DanK

2
@IsmaelMiguel Thực tiễn thông thường là dữ liệu chủ như thế này không bao giờ bị xóa khỏi cơ sở dữ liệu. Bạn chỉ xóa mềm nó bằng cách đặt cờ trên đó cho biết nó không còn khả dụng. Trong trường hợp cụ thể này, sẽ là một ý tưởng tốt khi có mối quan hệ khóa ngoài giữa các sản phẩm và đơn đặt hàng, điều đó có nghĩa là cơ sở dữ liệu sẽ xuất hiện lỗi khi bạn cố xóa một sản phẩm được tham chiếu bởi bất kỳ đơn đặt hàng nào.
Philipp

24

Tôi sẽ phải triển khai cơ sở dữ liệu với sếp của mình ...

Sử dụng phần mềm Quản lý cơ sở dữ liệu chuyên dụng có thể dễ dàng hơn đáng kể (xin lỗi; không thể cưỡng lại).

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngSản phẩm | tên sản phẩm

Nếu cơ sở dữ liệu này chỉ quan tâm đến việc "ghi nhật ký" sản phẩm nào được bán ở đâu, khi nào và bởi ai, thì bạn thể kéo dài Định nghĩa "cơ sở dữ liệu OK" đủ xa để bao quát nó. Nếu dữ liệu này đang được sử dụng cho bất cứ điều gì khác, thì nó thực sự rất kém.

Nhưng ...

Ứng dụng / truy vấn sử dụng dữ liệu này có phản hồi kém / chậm không? Nếu không, thì không có vấn đề thực sự cần giải quyết. Chắc chắn, nó trông và cảm thấy xấu xí, nhưng nếu nó hoạt động thì bạn sẽ không nhận được bất kỳ "điểm" nào cho thấy nó "có thể" tốt hơn.

Nếu bạn có thể tìm thấy các triệu chứng xác định (ví dụ như các vấn đề) trông giống như chúng gây ra bởi mô hình dữ liệu kém, thì nguyên mẫu là một giải pháp tốt hơn. Lấy một bản sao của một trong những "cơ sở dữ liệu" này, chuẩn hóa dữ liệu và xem liệu giải pháp của bạn có chạy tốt hơn không. Nếu nó tốt hơn đáng kể (và tôi hoàn toàn mong đợi rằng mọi hoạt động cập nhật trên dữ liệu này sẽ được cải thiện ồ ạt ), hãy quay lại với sếp của bạn và cho họ thấy sự cải thiện.

Hoàn toàn có thể tạo lại "chế độ xem một bảng" dữ liệu của mình với .. à .. Lượt xem.


11
Khả năng chống lại bảng duy nhất Weltanschauung thường đến từ những người thiếu kinh nghiệm với SQL, những người không hiểu về các phép nối - đặc biệt là liên quan đến dữ liệu bị thiếu, tức là các phép nối ngoài.
Robbie Dee

6
@RobbieDee Thông thường hơn, đó là từ những người đã thấy dữ liệu không chuẩn hóa bị hỏng do trở nên không nhất quán. Tôi là một người như vậy. Tôi chỉ xem xét loại cấu trúc này trong tình huống mà Phill gợi ý: đây là một loại bảng ghi nhật ký / báo cáo mà dữ liệu sẽ không bao giờ được cập nhật hoặc chỉ được cập nhật bằng cách xóa sạch và lấy lại hoàn toàn từ các nguồn khác.
jpmc26

2
Ngay cả khi ứng dụng hoạt động có thể chấp nhận được với cơ sở dữ liệu như thế này, thì nó vẫn không linh hoạt như cơ sở dữ liệu được chuẩn hóa đúng. Nếu tên cửa hàng hoặc tên công ty thay đổi, nó sẽ phải được cập nhật ở mọi nơi, thay vì chỉ trong một cửa hàng hoặc bảng công ty. Trong một số trường hợp, đó thực sự có thể là những gì bạn muốn (chẳng hạn như nếu dữ liệu chủ yếu được thu thập cho mục đích lưu trữ), nhưng chúng tôi cần biết thêm về ứng dụng cụ thể.
Zach Lipton

1
@Zach: đồng ý, đó là lý do tại sao nhật ký bán hàng có khả năng là trường hợp chấp nhận được cho việc này. Giả sử bạn muốn mỗi lần bán được liên kết với bất kỳ cửa hàng nào được đặt tên tại thời điểm bán được thực hiện, không phải "tên hiện tại của cửa hàng", sau đó cố gắng "bình thường hóa" điều này gây ra một số phức tạp đáng kể (vì tên cửa hàng ghi bảng sẽ cần phải là một chuỗi theo thời gian, không chỉ là một giá trị cho mỗi cửa hàng)
Steve Jessop

Có lẽ một nguyên tắc nhỏ là nếu sự phức tạp duy nhất được đưa ra bởi một chuẩn hóa được đề xuất là một vài truy vấn bây giờ cần tham gia vào chúng để chọn tất cả các cột mà chúng cần báo cáo, thì bạn không nên chạy đi để thực hiện thay đổi đó: - )
Steve Jessop

14

Tại sao một lược đồ quan hệ tốt cải thiện cơ sở dữ liệu?

Câu trả lời là: nó không phải lúc nào cũng cải thiện cơ sở dữ liệu. Bạn nên biết rằng những gì bạn có khả năng được dạy được gọi là Mẫu bình thường thứ ba .

Các hình thức khác có giá trị trong một số tình huống, đó là chìa khóa để trả lời câu hỏi của bạn. Ví dụ của bạn trông giống như Mẫu thường đầu tiên , nếu điều đó giúp bạn cảm thấy tốt hơn về trạng thái hiện tại của nó.

Các quy tắc 3NF thiết lập mối quan hệ giữa các dữ liệu "cải thiện" cơ sở dữ liệu:

  1. Ngăn chặn dữ liệu không hợp lệ xâm nhập vào hệ thống của bạn (nếu mối quan hệ là 1-1 thì nó sẽ gây ra lỗi mặc dù mã được viết ở trên nó). Nếu dữ liệu của bạn nhất quán trong cơ sở dữ liệu, ít có khả năng dẫn đến sự không nhất quán bên ngoài cơ sở dữ liệu của bạn.

  2. Nó cung cấp một cách để xác nhận mã (ví dụ: mối quan hệ nhiều-một là một tín hiệu để hạn chế các thuộc tính / hành vi của đối tượng). Khi viết mã để sử dụng cơ sở dữ liệu, đôi khi các lập trình viên nhận thấy cấu trúc dữ liệu như một chỉ báo về cách mã của họ sẽ hoạt động. Hoặc họ có thể cung cấp phản hồi hữu ích nếu cơ sở dữ liệu không khớp với mã của họ. (Điều này giống như mơ tưởng hơn, thật không may.)

  3. Cung cấp các quy tắc có thể giúp bạn giảm đáng kể các lỗi khi xây dựng cơ sở dữ liệu, để bạn không xây dựng nó dựa trên các yêu cầu tùy ý có thể xuất hiện bất cứ lúc nào trong vòng đời của cơ sở dữ liệu. Thay vào đó, bạn đang đánh giá một cách có hệ thống thông tin để đạt được các mục tiêu cụ thể.

  4. Cấu trúc cơ sở dữ liệu phù hợp dẫn đến hiệu suất được cải thiện bằng cách kết nối dữ liệu theo cách giảm thiểu lưu trữ dữ liệu, giảm thiểu các cuộc gọi lưu trữ để truy xuất dữ liệu, tối đa hóa tài nguyên trong bộ nhớ và / hoặc giảm thiểu sắp xếp / thao tác dữ liệu cho bộ dữ liệu cụ thể mà bạn có, so với truy vấn bạn đang có, so với truy vấn bạn đang có thi hành chống lại nó. Nhưng cấu trúc "phù hợp" phụ thuộc vào lượng dữ liệu, tính chất của dữ liệu, loại truy vấn, tài nguyên hệ thống, v.v. Bằng cách chuẩn hóa, bạn có thể làm cho hiệu suất kém hơn (nghĩa là nếu bạn tải tất cả dữ liệu dưới dạng 1 bảng - việc nối có thể chậm lại một truy vấn). Xử lý giao dịch (OLTP) so với kinh doanh thông minh (kho dữ liệu) rất khác nhau.

Trong một công ty nhỏ với các tập dữ liệu nhỏ, bạn có thể thấy rằng không có gì sai với cách thức hiện tại. Ngoại trừ, nếu bạn phát triển, sẽ rất khó để "sửa chữa" sau này, bởi vì khi bảng trở nên lớn, các hệ thống sử dụng nó sẽ có thể chậm hơn.

Thông thường bạn sẽ muốn nhấn mạnh các giao dịch nhanh khi một công ty phát triển. Tuy nhiên, nếu bạn dành thời gian cho dự án này ngay bây giờ thay vì những thứ khác mà công ty có thể cần gấp hơn, bạn có thể không bao giờ gặp vấn đề đó vì công ty của bạn không bao giờ thực sự phát triển. Đó là "thách thức tối ưu hóa trước" - nơi dành thời gian quý báu của bạn ngay bây giờ.

Chúc may mắn!


4
Không đề cập đến nhưng tôi nghĩ một điểm quan trọng đối với các lập trình viên là việc chỉnh sửa một "thứ" chỉ yêu cầu chỉnh sửa một hàng duy nhất thay vì phải lặp lại toàn bộ cơ sở dữ liệu để tìm và thay thế điều đó.
slebetman

@slebetman Bạn không bao giờ nên có một vòng lặp bên mã để cập nhật nhiều hàng trong một bảng, bất kể nó có được chuẩn hóa hay không. Sử dụng một WHEREmệnh đề. Tất nhiên, những điều này vẫn có thể sai, nhưng ít có khả năng trong tình huống được chuẩn hóa vì bạn chỉ phải khớp một hàng qua khóa chính.
jpmc26

@ jpmc26: Bằng cách lặp cơ sở dữ liệu, tôi có nghĩa là xây dựng một truy vấn để cập nhật tất cả các hàng bị ảnh hưởng. Đôi khi một WHERE đủ. Nhưng tôi đã thấy các cấu trúc không linh hoạt yêu cầu các mục phụ vào cùng một bảng để có được tất cả các hàng bị ảnh hưởng mà không ảnh hưởng đến các hàng không nên thay đổi. Tôi thậm chí đã nhìn thấy các cấu trúc trong đó một truy vấn không thể thực hiện công việc (thực thể cần thay đổi nằm trong các cột khác nhau tùy theo hàng)
slebetman

Nhiều câu trả lời tuyệt vời cho câu hỏi này, và điều này cũng không ngoại lệ.
Mike Chamberlain

11

Có nhiều lý do tại sao sử dụng một "bảng thần" lớn là xấu. Tôi sẽ thử và minh họa các vấn đề với cơ sở dữ liệu ví dụ. Giả sử bạn đang cố gắng mô hình các sự kiện thể thao. Chúng tôi sẽ nói rằng bạn muốn mô hình hóa các trò chơi và các đội chơi trong các trò chơi đó. Một thiết kế có nhiều bảng có thể trông như thế này (mục đích này rất đơn giản vì vậy đừng bị cuốn vào những nơi có thể áp dụng chuẩn hóa hơn):

Teams
Id | Name | HomeCity

Games
Id | StartsAt | HomeTeamId | AwayTeamId | Location

và một cơ sở dữ liệu bảng duy nhất sẽ trông như thế này

TeamsAndGames
Id | TeamName | TeamHomeCity | GameStartsAt | GameHomeTeamId | GameAwayTeamId | Location

Đầu tiên, chúng ta hãy nhìn vào việc tạo các chỉ số trên các bảng đó. Nếu tôi cần một chỉ số về thành phố quê hương cho một đội, tôi có thể thêm nó vào Teamsbảng hoặc TeamsAndGamesbảng khá dễ dàng. Hãy nhớ rằng bất cứ khi nào bạn tạo một chỉ mục, nó cần được lưu trữ trên đĩa ở đâu đó và được cập nhật khi các hàng được thêm vào bảng. Trong trường hợp của Teamsbảng này là khá đơn giản. Tôi đưa vào một nhóm mới, cơ sở dữ liệu cập nhật chỉ mục. Nhưng còn về cái gì TeamsAndGames? Vâng, điều tương tự áp dụng từTeamsthí dụ. Tôi thêm một nhóm, chỉ số được cập nhật. Nhưng nó cũng xảy ra khi tôi thêm một trò chơi! Mặc dù trường đó sẽ là null cho một trò chơi, nhưng chỉ mục vẫn phải được cập nhật và lưu trữ trên đĩa cho trò chơi đó. Đối với một chỉ số, điều này không có vẻ quá tệ. Nhưng khi bạn cần nhiều chỉ mục cho nhiều thực thể được nhồi nhét vào bảng này, bạn sẽ lãng phí rất nhiều không gian lưu trữ các chỉ mục và rất nhiều thời gian xử lý để cập nhật chúng cho những thứ mà chúng không áp dụng.

Thứ hai, thống nhất dữ liệu. Trong trường hợp sử dụng hai bảng riêng biệt, tôi có thể sử dụng các khóa ngoại từ Gamesbảng này đến Teamsbảng để xác định đội nào đang chơi trong một trò chơi. Và giả sử tôi làm cho các cột HomeTeamIdAwayTeamIdcột không thể rỗng, cơ sở dữ liệu sẽ đảm bảo rằng mỗi trò chơi tôi đặt có 2 đội và các đội đó tồn tại trong cơ sở dữ liệu của tôi. Nhưng những gì về kịch bản bảng duy nhất? Chà, vì có nhiều thực thể trong bảng này, các cột đó sẽ không thể thực hiện được (bạn có thể làm cho chúng không thể rỗng và xóa dữ liệu rác trong đó, nhưng đó chỉ là một ý tưởng khủng khiếp). Nếu các cột đó là null, cơ sở dữ liệu có thể không còn đảm bảo rằng khi bạn chèn một trò chơi có hai đội.

Nhưng nếu bạn quyết định chỉ đi cho nó bằng cách nào? Bạn thiết lập các khóa ngoại sao cho các trường đó quay lại một thực thể khác trong cùng một bảng. Nhưng bây giờ cơ sở dữ liệu sẽ chỉ đảm bảo rằng các thực thể đó tồn tại trong bảng, chứ không phải chúng là loại chính xác. Bạn có thể rất dễ dàng đặt GameHomeTeamIdID của một trò chơi khác và cơ sở dữ liệu sẽ không phàn nàn gì cả. Nếu bạn đã thử trong kịch bản nhiều bảng, cơ sở dữ liệu sẽ phù hợp.

Bạn có thể cố gắng giảm thiểu những vấn đề này bằng cách nói "tốt, chúng tôi sẽ chỉ đảm bảo rằng chúng tôi không bao giờ làm điều đó trong mã". Nếu bạn tự tin vào khả năng viết mã không có lỗi lần đầu tiên và khả năng tính đến mọi sự kết hợp kỳ lạ của người dùng có thể thử, hãy tiếp tục. Cá nhân tôi không tự tin vào khả năng của mình để làm một trong những điều đó, vì vậy tôi sẽ để cơ sở dữ liệu cung cấp cho tôi một mạng lưới an toàn bổ sung.

(Điều này thậm chí còn tệ hơn nếu thiết kế của bạn là nơi bạn sao chép tất cả dữ liệu có liên quan giữa các hàng thay vì sử dụng khóa ngoại. Mọi lỗi chính tả / dữ liệu khác sẽ khó giải quyết. "Hoặc nếu đó là cố ý (vì họ là hai người riêng biệt)?)

Thứ ba, hầu hết mọi cột cần phải là null hoặc phải được điền với dữ liệu được sao chép hoặc rác. Một trò chơi không cần một TeamNamehoặc TeamHomeCity. Vì vậy, mỗi trò chơi đều cần một số loại giữ chỗ trong đó hoặc nó cần phải vô hiệu. Và nếu nó là nullable, cơ sở dữ liệu sẽ vui vẻ chơi một trò chơi không có TeamName. Nó cũng sẽ đưa một nhóm không có tên, ngay cả khi logic kinh doanh của bạn nói rằng điều đó sẽ không bao giờ xảy ra.

Có một số lý do khác khiến bạn muốn có các bảng riêng biệt (bao gồm cả việc duy trì sự tỉnh táo của nhà phát triển). Thậm chí có một vài lý do tại sao một bảng lớn hơn có thể tốt hơn (việc không chuẩn hóa đôi khi cải thiện hiệu suất). Các kịch bản đó rất ít và xa (và thường được xử lý tốt nhất khi bạn có số liệu hiệu suất để cho thấy rằng đó thực sự là vấn đề, không phải là một chỉ số bị thiếu hoặc một cái gì khác).

Cuối cùng, phát triển một cái gì đó sẽ dễ dàng để duy trì. Chỉ vì nó "hoạt động" không có nghĩa là nó ổn. Cố gắng duy trì các bảng thần (như các lớp thần) là một cơn ác mộng. Bạn chỉ đang tự đặt ra cho nỗi đau sau này.


1
"Đội: Id | Tên | HomeCity". Chỉ cần đảm bảo rằng lược đồ dữ liệu của bạn không làm cho ứng dụng của bạn tuyên bố không chính xác rằng Super Bowl XXXIV đã giành được bởi LA Rams. Trong khi đó SB XXXIV sẽ xuất hiện trong một truy vấn cho tất cả các giải vô địch mà đội hiện được gọi là LA Rams. Có những "bảng thần" tốt hơn và tồi tệ hơn, và bạn chắc chắn đã trình bày một bảng xấu. Một cái tốt hơn sẽ là "ID trò chơi | tên đội nhà | thành phố đội nhà | tên đội khách | đội bóng thành phố | trò chơi bắt đầu lúc | vv ...". Đây là một nỗ lực đầu tiên để mô hình hóa thông tin như "New Orleans Saints @ Chicago Bears 1p East".
Steve Jessop

6

Trích dẫn trong ngày: " Lý thuyết và thực hành nên giống nhau ... về lý thuyết "

Bảng không chuẩn hóa

Bảng giữ tất cả duy nhất của bạn chứa dữ liệu dư thừa có một lợi thế: nó giúp báo cáo trên các dòng của nó rất đơn giản để mã hóa và thực thi nhanh vì bạn không phải thực hiện bất kỳ phép nối nào. Nhưng điều này với chi phí cao:

  • Nó giữ các bản sao quan hệ dư thừa (ví dụ IngCompanyIDvrCompanyName). Cập nhật dữ liệu chủ có thể yêu cầu cập nhật nhiều dòng hơn trong lược đồ đã chuẩn hóa.
  • Nó trộn lẫn mọi thứ. Bạn không thể đảm bảo kiểm soát truy cập dễ dàng ở cấp cơ sở dữ liệu, ví dụ: đảm bảo rằng người dùng A chỉ có thể cập nhật thông tin công ty và người dùng B chỉ thông tin sản phẩm.
  • Bạn không thể đảm bảo quy tắc nhất quán ở cấp cơ sở dữ liệu (ví dụ: khóa chính để thực thi rằng chỉ có một tên công ty cho id công ty).
  • Bạn không được hưởng lợi hoàn toàn từ trình tối ưu hóa DB, người có thể xác định các chiến lược truy cập tối ưu cho một truy vấn phức tạp, tận dụng kích thước của các bảng được chuẩn hóa và thống kê của một số chỉ mục. Điều này có thể nhanh chóng bù đắp lợi ích hạn chế của việc tránh tham gia.

Bảng chuẩn hóa

Những nhược điểm trên là những lợi thế cho lược đồ chuẩn hóa. Tất nhiên, các truy vấn có thể phức tạp hơn một chút để viết.

Nói tóm lại, lược đồ chuẩn hóa thể hiện cấu trúc và quan hệ giữa dữ liệu của bạn tốt hơn nhiều. Tôi sẽ bị khiêu khích và nói rằng đó là một loại khác biệt so với giữa kỷ luật bắt buộc phải sử dụng một bộ ngăn kéo văn phòng được đặt hàng và việc sử dụng thùng rác dễ dàng.


5

Tôi nghĩ có ít nhất hai phần cho câu hỏi của bạn:

1. Tại sao các thực thể thuộc các loại khác nhau không được lưu trữ trong cùng một bảng?

Các câu trả lời quan trọng nhất ở đây là khả năng đọc mã và tốc độ. A SELECT name FROM companies WHERE id = ?chỉ dễ đọc hơn nhiều so với a SELECT companyName FROM masterTable WHERE companyId = ?và bạn ít có khả năng vô tình truy vấn vô nghĩa (ví dụ: SELECT companyName FROM masterTable WHERE employeeId = ?không thể thực hiện được khi các công ty và nhân viên được lưu trữ trong các bảng khác nhau). Đối với tốc độ, dữ liệu từ bảng cơ sở dữ liệu được lấy ra bằng cách đọc toàn bộ bảng tuần tự hoặc bằng cách đọc từ một chỉ mục. Cả hai đều nhanh hơn nếu bảng / chỉ mục chứa ít dữ liệu hơn và đó là trường hợp nếu dữ liệu được lưu trữ trong các bảng khác nhau (và bạn chỉ cần đọc một trong các bảng / chỉ mục).

2. Tại sao các thực thể của một loại phải được chia thành các thực thể phụ được lưu trữ trong các bảng khác nhau?

Ở đây, lý do chủ yếu là để ngăn chặn sự không nhất quán dữ liệu. Với cách tiếp cận bảng duy nhất, đối với hệ thống quản lý đơn hàng, bạn có thể lưu trữ tên khách hàng, địa chỉ khách hàng và ID sản phẩm của sản phẩm mà khách hàng đã đặt hàng dưới dạng một thực thể. Nếu một khách hàng đặt mua nhiều sản phẩm, bạn sẽ có nhiều phiên bản về tên và địa chỉ của khách hàng trong cơ sở dữ liệu của bạn. Trong trường hợp tốt nhất, bạn vừa nhận được dữ liệu trùng lặp trong cơ sở dữ liệu của mình, điều này có thể làm chậm dữ liệu một chút. Nhưng một trường hợp tồi tệ hơn là ai đó (hoặc một số mã) đã mắc lỗi khi dữ liệu được nhập để một công ty kết thúc với các địa chỉ khác nhau trong cơ sở dữ liệu của bạn. Điều này một mình là đủ xấu. Nhưng nếu bạn truy vấn địa chỉ của một công ty dựa trên tên của nó (ví dụ:SELECT companyAddress FROM orders WHERE companyName = ? LIMIT 1) bạn sẽ tự ý trả lại một trong hai địa chỉ và thậm chí sẽ không nhận ra rằng có sự không nhất quán. Nhưng mỗi lần bạn chạy truy vấn, bạn thực sự có thể nhận được một địa chỉ khác nhau, tùy thuộc vào cách truy vấn của bạn được giải quyết bên trong bởi DBMS. Điều này có thể sẽ phá vỡ ứng dụng của bạn ở một nơi khác và nguyên nhân sâu xa của sự cố đó sẽ rất khó tìm thấy.

Với cách tiếp cận nhiều bảng, bạn sẽ nhận ra rằng có một sự phụ thuộc chức năng từ tên công ty đến địa chỉ công ty (nếu một công ty chỉ có một địa chỉ), bạn sẽ lưu trữ bộ dữ liệu (companyName, companyAddress) trong một bảng (ví dụ: company) và tuple (ProductId, companyName) trong một bảng khác (ví dụ order). Một UNIQUEràng buộc trên companybảng sau đó có thể thực thi rằng mỗi công ty chỉ có một địa chỉ duy nhất trong cơ sở dữ liệu của bạn để không có sự không nhất quán nào về địa chỉ công ty có thể phát sinh.

Lưu ý: trong thực tế, vì lý do hiệu suất, bạn có thể tạo một công ty duy nhất cho mỗi công ty và sử dụng nó làm khóa ngoại thay vì sử dụng trực tiếp tên công ty. Nhưng cách tiếp cận chung vẫn giữ nguyên.


3

TL; DR - Họ đang thiết kế cơ sở dữ liệu dựa trên cách họ được dạy khi còn đi học.

Tôi có thể đã viết câu hỏi này 10 năm trước. Phải mất một thời gian để tôi hiểu tại sao những người tiền nhiệm của tôi thiết kế cơ sở dữ liệu của họ theo cách họ đã làm. Bạn đang làm việc với ai đó:

  1. Đạt được hầu hết các kỹ năng thiết kế cơ sở dữ liệu của họ bằng cách sử dụng Excel làm cơ sở dữ liệu hoặc
  2. Họ đang sử dụng những thực hành tốt nhất từ ​​khi họ ra khỏi trường.

Tôi không nghi ngờ đó là số 1 vì bạn thực sự có số ID trong bảng của mình, vì vậy tôi sẽ giả sử số 2.

Sau khi tôi ra khỏi trường, tôi đang làm việc cho một cửa hàng sử dụng AS / 400 (còn gọi là IBM i). Tôi tìm thấy một số điều kỳ lạ trong cách họ thiết kế cơ sở dữ liệu của họ và bắt đầu ủng hộ chúng tôi thực hiện các thay đổi để làm theo cách tôi được dạy cách thiết kế cơ sở dữ liệu. (Lúc đó tôi đã bị câm)

Phải mất một lập trình viên lớn tuổi hơn để giải thích cho tôi tại sao mọi việc được thực hiện theo cách đó. Họ đã không thay đổi lược đồ vì nó sẽ khiến các chương trình cũ hơn tôi bị hỏng. Theo nghĩa đen, mã nguồn cho một chương trình có ngày tạo ra một năm trước khi tôi được sinh ra. Trên hệ thống chúng tôi đang làm việc, các chương trình của họ phải triển khai tất cả logic và hoạt động mà trình hoạch định truy vấn cơ sở dữ liệu của bạn xử lý cho bạn. (Bạn có thể thấy điều đó bằng cách chạy EXPLAIN trên một trong các truy vấn của bạn)

Anh ấy đã cập nhật về các kỹ thuật tôi đang cố gắng thực hiện, nhưng giữ cho hệ thống hoạt động quan trọng hơn là thay đổi "bởi vì nó đi ngược lại những gì tôi được dạy". Mỗi dự án mới, một trong hai chúng tôi bắt đầu sử dụng tốt nhất mô hình quan hệ mà chúng tôi có thể làm được. Thật không may, các lập trình viên / chuyên gia tư vấn khác từ thời đó vẫn thiết kế cơ sở dữ liệu của họ như thể họ đang làm việc với các ràng buộc trước đây của hệ thống đó.


Một số ví dụ về những gì tôi gặp không phù hợp với mô hình quan hệ:

  • Ngày được lưu trữ dưới dạng số ngày Julian yêu cầu tham gia vào bảng ngày để có được ngày thực tế.
  • Các bảng không chuẩn hóa với các cột liên tiếp cùng loại (ví dụ code1,code2, ..., code20)
  • Các cột CHAR có độ dài NxM đại diện cho một mảng gồm N chuỗi có độ dài M.

Những lý do mà tôi được đưa ra cho những quyết định thiết kế đó đều dựa trên những ràng buộc của hệ thống khi cơ sở dữ liệu được thiết kế lần đầu tiên.

Ngày - Tôi được cho biết phải mất nhiều thời gian xử lý hơn để sử dụng các hàm ngày (tháng hoặc ngày hoặc ngày trong tuần) để xử lý một ngày so với ngày tạo ra một bảng mỗi ngày có thể với tất cả thông tin đó.

Các cột tuần tự cùng loại - Môi trường lập trình mà họ đã cho phép một chương trình tạo một biến mảng trên một phần của hàng. Và đó là một cách dễ dàng hơn để giảm số lượng các hoạt động đọc.

Các cột CHAR Độ dài NxM - Dễ dàng chuyển các giá trị cấu hình vào một cột để giảm các thao tác đọc tệp.

Một ví dụ được quan niệm kém trong C tương đương để phản ánh môi trường lập trình mà họ có:

#define COURSE_LENGTH 4
#define NUM_COURSES 4
#define PERIOD_LENGTH 2

struct mytable {
    int id;
    char periodNames[NUM_COURSES * PERIOD_LENGTH];  // NxM CHAR Column
    char course1[COURSE_LENGTH];
    char course2[COURSE_LENGTH];
    char course3[COURSE_LENGTH];
    char course4[COURSE_LENGTH];
};

...

// Example row
struct mytable row = {.id= 1, .periodNames="HRP1P2P8", .course1="MATH", .course2="ENGL", .course3 = "SCI ", .course4 = "READ"};

char *courses; // Pointer used to access the sequential columns
courses = (char *)&row.course1;


for(int i = 0; i < NUM_COURSES; i++) {

    printf("%d: %.*s -> %.*s\n",i+1, PERIOD_LENGTH, &row.periodNames[PERIOD_LENGTH * i], COURSE_LENGTH,&courses[COURSE_LENGTH*i]);
}

Đầu ra

1: Nhân sự -> TOÁN
2: P1 -> Tiếng Anh
3: P2 -> SCI
4: P8 -> ĐỌC

Theo những gì tôi đã nói, một số trong số này được coi là thực hành tốt nhất tại thời điểm đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.