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 Teams
bảng hoặc TeamsAndGames
bả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 Teams
bả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ừTeams
thí 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ừ Games
bảng này đến Teams
bả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 HomeTeamId
và AwayTeamId
cộ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 GameHomeTeamId
ID 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 TeamName
hoặ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.