MySQL: nhiều bảng hoặc một bảng có nhiều cột?


124

Vì vậy, đây là nhiều hơn một câu hỏi thiết kế.

Tôi có một khóa chính (giả sử ID người dùng) và tôi có hàng tấn thông tin liên quan đến người dùng đó.

Tôi có nên chia nhiều bảng thành các loại theo thông tin hay tôi chỉ nên có một bảng có nhiều cột?

Cách tôi thường làm là có nhiều bảng, giả sử, một bảng cho dữ liệu sử dụng ứng dụng, một bảng cho thông tin hồ sơ, một bảng cho mã thông báo đầu cuối, v.v. để giữ mọi thứ có tổ chức.

Gần đây, một số người nói với tôi rằng tốt hơn là không làm theo cách đó và có một bảng có nhiều cột là tốt. Vấn đề là, tất cả các cột có cùng khóa chính.

Tôi khá mới với thiết kế cơ sở dữ liệu vì vậy cách tiếp cận nào tốt hơn và ưu và nhược điểm là gì?

Cách thông thường để làm điều đó là gì?


Để rõ ràng, hãy sửa tôi nếu tôi sai, nhưng tôi nghĩ "nhiều bảng" có thể được hiểu là bảng liên kết / liên kết: en.wikipedia.org/wiki/Associative_entity
cellepo

1
Là cơ sở dữ liệu này cần thiết cho mục đích phân tích hoặc để xử lý hoạt động / giao dịch?
Alexander Radev

Câu trả lời:


112

Bất kỳ thời gian nào thông tin là một (một người dùng có một tên và mật khẩu), thì có lẽ nên có một bảng, vì nó làm giảm số lượng tham gia mà cơ sở dữ liệu sẽ cần phải thực hiện để lấy kết quả. Tôi nghĩ rằng một số cơ sở dữ liệu có giới hạn về số lượng cột trên mỗi bảng, nhưng tôi sẽ không lo lắng về nó trong các trường hợp thông thường và bạn luôn có thể phân tách nó sau nếu bạn cần.

Nếu dữ liệu là một-nhiều (mỗi người dùng có hàng ngàn hàng thông tin sử dụng), thì nó nên được chia thành các bảng riêng biệt để giảm dữ liệu trùng lặp (dữ liệu trùng lặp gây lãng phí không gian lưu trữ, không gian bộ nhớ cache và khiến cơ sở dữ liệu khó bảo trì hơn ).

Bạn có thể thấy bài viết Wikipedia về bình thường hóa cơ sở dữ liệu rất thú vị, vì nó thảo luận về lý do cho điều này sâu hơn:

Chuẩn hóa cơ sở dữ liệu là quá trình tổ chức các trường và bảng của cơ sở dữ liệu quan hệ để giảm thiểu sự dư thừa và phụ thuộc. Bình thường hóa thường bao gồm việc chia các bảng lớn thành các bảng nhỏ hơn (và ít dự phòng hơn) và xác định mối quan hệ giữa chúng. Mục tiêu là cô lập dữ liệu sao cho việc bổ sung, xóa và sửa đổi một trường có thể được thực hiện chỉ trong một bảng và sau đó được truyền qua phần còn lại của cơ sở dữ liệu thông qua các mối quan hệ được xác định.

Không chuẩn hóa cũng là điều cần lưu ý, bởi vì có những trường hợp lặp lại dữ liệu tốt hơn (vì nó làm giảm khối lượng công việc mà cơ sở dữ liệu cần làm khi đọc dữ liệu). Tôi thực sự khuyên bạn nên làm cho dữ liệu của mình được chuẩn hóa nhất có thể để bắt đầu và chỉ chuẩn hóa nếu bạn nhận thấy vấn đề về hiệu suất trong các truy vấn cụ thể.


Cảm ơn câu trả lời của bạn, vì vậy sau khi đọc nó, tôi nghĩ điều tôi đang nói đến là tình huống thông tin một-một, khi người dùng có nhiều cột một-một.
Xavier_Ex

@Xavier_Ex - Vâng, nếu chỉ có một cột cho mỗi người dùng, thì chỉ cần một bảng người dùng khổng lồ sẽ dễ dàng làm việc hơn (và công cụ DB dễ dàng tối ưu hóa hơn rất nhiều).
Brendan Long

Bài viết đã chỉnh sửa của bạn cung cấp thêm thông tin hữu ích! Tôi có một mối quan tâm mới là nếu một số cột sẽ được cập nhật thường xuyên, tôi có nên đặt chúng vào một bảng riêng không? Ví dụ: ngày sinh của người dùng sẽ không được cập nhật bao giờ, nhưng mã thông báo phía sau có thể bị vô hiệu sau một khoảng thời gian và sẽ yêu cầu cập nhật thường xuyên. Sẽ tốt hơn nếu tôi tách các bảng theo cách này để cải thiện hiệu suất? Bây giờ tôi sẽ đọc về wiki mà bạn đã đề cập :)
Xavier_Ex

@Xavier_Ex - Tôi sẽ không đề xuất nó. Bạn có được hiệu suất tốt hơn đáng kể khi bạn có thể tra cứu tất cả dữ liệu bạn cần trong một bảng (xem bài viết về sự không chuẩn hóa). Tham gia rất tốn kém vì (1) họ yêu cầu tra cứu dữ liệu ở nhiều nơi, có thể bao gồm tìm kiếm trên đĩa quay, (2) thường yêu cầu nhiều chỉ mục và một số loại hợp nhất và (3) họ làm cho việc lập kế hoạch truy vấn khó hơn, nhưng không chỉ mất thời gian, nhưng cũng làm tăng khả năng trình tối ưu hóa truy vấn sẽ gặp sự cố (và các truy vấn được tối ưu hóa kém có thể rất chậm).
Brendan Long

1
Gần đây tôi đã phải đối mặt với vấn đề tương tự, bởi vì các bảng MySQL InnoDB có giới hạn độ dài tương đối nhỏ (~ 8000 byte). Trong bảng vấn đề của tôi (dữ liệu từ các biểu mẫu bảo hiểm rất dài, hơn 100 cột), chúng tôi có nhiều cột varchar, tất cả UTF8. Vì vậy, chúng tôi dễ dàng lấp đầy giới hạn ~ 8000 byte và luôn nhận được "lỗi 139 từ công cụ lưu trữ". Vì vậy, chúng tôi đã phải chia bàn. (Chúng tôi đã thử nghiệm với định dạng Barracuda mới hơn và nó đã hoạt động mà không bị chia tách, nhưng máy chủ của khách hàng của chúng tôi vẫn sử dụng MySQL 5.0).
MV.

12

Một bàn lớn thường là một lựa chọn kém. Các bảng liên quan là những gì cơ sở dữ liệu quan hệ được thiết kế để làm việc với. Nếu bạn lập chỉ mục đúng và biết cách viết các truy vấn hiệu suất, chúng sẽ hoạt động tốt.

Khi các bảng có quá nhiều cột, thì bạn có thể gặp vấn đề với kích thước thực của trang mà cơ sở dữ liệu đang lưu trữ thông tin. Bản ghi có thể quá lớn đối với trang, trong đó bạn có thể cuối cùng không thể tạo hoặc cập nhật một bản ghi cụ thể khiến người dùng không hài lòng hoặc ít nhất bạn có thể (trong SQL Server) kiểu dữ liệu (với một bộ quy tắc bạn cần tra cứu nếu bạn đang làm điều này) nhưng nếu nhiều bản ghi sẽ tràn kích thước trang, bạn có thể tạo ra các vấn đề hiệu suất run rẩy. Bây giờ cách MYSQL xử lý các trang và liệu bạn có gặp sự cố khi kích thước trang tiềm năng quá lớn hay không là điều bạn sẽ phải tìm trong tài liệu cho cơ sở dữ liệu đó.


1
Ah giọng nói khác nhau! Mà luôn luôn là tuyệt vời. Cảm ơn vì thông tin của bạn! Tôi sẽ đảm bảo rằng tôi nhận thức được điều đó khi tôi tạo các bảng của mình ... nhưng tôi không biết rằng tôi sẽ phải nhận thức được những thứ cấp thấp như vậy ban đầu.
Xavier_Ex

4

Tôi có một ví dụ tốt. Cơ sở dữ liệu quá chuẩn hóa với tập hợp các mối quan hệ sau:

people -> rel_p2staff -> staff

people -> rel_p2prosp -> prospects

Trường hợp mọi người có chi tiết về tên và người, nhân viên chỉ có chi tiết hồ sơ nhân viên, khách hàng tiềm năng chỉ có chi tiết về khách hàng tiềm năng và các bảng rel là các bảng quan hệ với các khóa ngoại từ những người liên kết với nhân viên và khách hàng tiềm năng.

Kiểu thiết kế này mang trên toàn bộ cơ sở dữ liệu.

Bây giờ để truy vấn tập hợp quan hệ này, đó là tham gia nhiều bảng mỗi lần, đôi khi 8 và nhiều hơn tham gia bảng. Nó đã hoạt động tốt cho đến giữa năm nay, khi nó bắt đầu trở nên rất chậm khi chúng tôi vượt qua 40000 hồ sơ của mọi người.

Lập chỉ mục và tất cả các loại trái cây treo thấp đã được sử dụng hết năm ngoái, tất cả các truy vấn được tối ưu hóa để hoàn thiện. Đây là phần cuối của thiết kế và quản lý được chuẩn hóa cụ thể hiện đã phê duyệt việc xây dựng lại toàn bộ ứng dụng phụ thuộc vào nó cũng như cơ cấu lại cơ sở dữ liệu, trong thời hạn 6 tháng. $$$$ Ouch.

Giải pháp sẽ là có một mối quan hệ trực tiếp cho people -> staffpeople -> prospect


Sẽ được quan tâm để biết làm thế nào xây dựng lại đã đi? Bạn đã kết thúc việc thiết kế một cái gì đó tương tự như thừa kế bảng đơn trong đó bạn có typemột staffhoặc một prospect?
Coderama

1
Đã đi với những người có quan hệ trực tiếp -> nhân viên và người -> khách hàng tiềm năng, làm việc say mê, dễ sử dụng, truy vấn nhanh.
Vlad

4

Đã xem qua điều này và là một người đã từng sử dụng MySQL rất nhiều và sau đó chuyển sang Postgres gần đây, một trong những lợi thế lớn là bạn có thể thêm các đối tượng JSON vào một trường trong Postgres.

Vì vậy, nếu bạn ở trong tình huống này, bạn không nhất thiết phải quyết định giữa một bảng lớn có nhiều cột và tách nó ra, nhưng bạn có thể hợp nhất các cột thành các đối tượng JSON để giảm nó, thay vì địa chỉ là 5 cột, nó chỉ có thể trở thành một. Bạn cũng có thể truy vấn đối tượng đó.


Điều gì về hiệu suất của anh ta khi sử dụng đối tượng json trong khi truy vấn?
dagalti

1
@dagalti hiệu suất là tốt cho các ứng dụng tôi đã sử dụng nó trên. Tôi chưa thực hiện điểm chuẩn của riêng mình về nó, nhưng điều này có thể hữu ích với bạn: arangodb.com/2018/02/iêu
moinhaque

3

Hãy tự hỏi mình những câu hỏi này nếu bạn đặt mọi thứ vào một bảng, bạn sẽ có nhiều hàng cho người dùng đó chứ? Nếu bạn phải cập nhật một người dùng, bạn có muốn giữ một dấu vết kiểm toán không? Người dùng có thể có nhiều hơn một phiên bản của một thành phần dữ liệu không? (ví dụ như số điện thoại) bạn sẽ có trường hợp bạn muốn thêm một yếu tố hoặc tập hợp các yếu tố sau? nếu bạn trả lời có thì rất có thể bạn muốn có các bảng con có mối quan hệ khóa ngoài.

Ưu điểm của bảng cha / con là tính toàn vẹn dữ liệu, hiệu suất thông qua các chỉ mục (có, bạn cũng có thể làm điều đó trên bảng phẳng) và IMO dễ duy trì hơn nếu bạn cần thêm một trường sau đó, đặc biệt nếu đó sẽ là trường bắt buộc.

Nhược điểm thiết kế khó hơn, các truy vấn trở nên phức tạp hơn một chút

Nhưng, có nhiều trường hợp một bàn phẳng lớn sẽ phù hợp để bạn phải xem xét tình huống của mình để quyết định.


Cảm ơn bạn đã nhắc nhở tôi! Vì vậy, trong trường hợp của tôi, tôi chỉ xem xét trường hợp mỗi người dùng không thể có nhiều hơn một hàng nên tất cả các trường thông tin là một đối một. Ngoài ra, người dùng không thể có nhiều hơn một thể hiện của cùng một yếu tố như tôi tin vào khái niệm một yếu tố không thể tồn tại ở nhiều nơi. Đối với câu hỏi thứ ba, vâng tôi có thể thêm nhiều yếu tố vào bảng nhưng chúng sẽ không phá vỡ các yêu cầu tôi đã đề cập ở trên. Tôi nghĩ rằng bảng cha / con là tốt khi tôi muốn liên kết nhiều hàng với một người dùng, nhưng trong trường hợp này, mối quan tâm của tôi là người dùng có nhiều cột một-một.
Xavier_Ex

ngay cả khi tất cả các yếu tố hiện đang là một, điều đó không làm giảm nhu cầu hoặc mong muốn có bảng cha mẹ / con IMO. Giữ một bản ghi dữ liệu thay đổi là một lần sử dụng. lười tải đồ vật là khác. trong khi có những lợi ích cho một cấu trúc bảng duy nhất thì cũng có những lợi ích đối với bố trí con cái (mặc dù tôi cũng đã thấy mọi người đi đến cực đoan với những điều này).
Brian

1

Tôi đã hoàn thành một số loại thiết kế cơ sở dữ liệu. Đối với tôi, nó phụ thuộc vào độ khó của hệ thống với quản lý cơ sở dữ liệu; Vâng, đúng là chỉ có dữ liệu duy nhất ở một nơi nhưng thực sự rất khó để thực hiện các truy vấn với cơ sở dữ liệu được chuẩn hóa quá mức với nhiều bản ghi. Chỉ cần kết hợp hai lược đồ; sử dụng một bảng lớn nếu bạn cảm thấy rằng bạn sẽ có một hồ sơ lớn khó duy trì giống như facebook, gmail, v.v. và sử dụng bảng khác nhau cho một bộ bản ghi cho hệ thống đơn giản ... đây chỉ là ý kiến ​​của tôi .. tôi hy vọng nó có thể giúp .. chỉ cần làm điều đó .. bạn có thể làm điều đó ... :)


1
"Sử dụng một bảng lớn nếu bạn sẽ có một hồ sơ lớn .." Nhưng Facebook, Google không lưu trữ dữ liệu người dùng trong một bảng, họ tách chúng thành nhiều bảng.
Yami Odymel

0

Cách thông thường để làm điều này sẽ là sử dụng các bảng khác nhau như trong lược đồ sao hoặc lược đồ bông tuyết. Howeevr, tôi sẽ căn cứ chiến lược này thành hai lần. Tôi tin vào lý thuyết rằng dữ liệu chỉ nên tồn tại ở một nơi, ở đó cho lược đồ mà tôi đã đề cập sẽ hoạt động tốt. Tuy nhiên, tôi cũng tin rằng đối với các công cụ báo cáo và bộ BI, cách tiếp cận cột sẽ rất có lợi vì nó hỗ trợ nhiều hơn cho nhu cầu báo cáo. Các cách tiếp cận theo cột như những phương pháp với infobright.org có hiệu suất và nén hiệu suất rất lớn khiến việc sử dụng cả hai cách tiếp cận này vô cùng hữu ích. Rất nhiều công ty bắt đầu nhận ra rằng chỉ có một kiến ​​trúc cơ sở dữ liệu trong tổ chức không hỗ trợ đầy đủ các nhu cầu của họ. Rất nhiều công ty đang thực hiện cả khái niệm có nhiều kiến ​​trúc cơ sở dữ liệu.


Cảm ơn thông tin, nhưng xin lỗi tôi không hiểu câu trả lời của bạn ... Tôi sẽ thực hiện tìm kiếm trên hai lược đồ mà bạn đã đề cập đầu tiên ...
Xavier_Ex

-4

Tôi nghĩ rằng có một bảng duy nhất hiệu quả hơn nhưng bạn nên chắc chắn rằng bảng được tổ chức theo cách nó thể hiện mối quan hệ, xu hướng cũng như sự khác biệt trong các biến của cùng một hàng. ví dụ: nếu bảng hiển thị tuổi và điểm của học sinh, bạn nên sắp xếp bảng theo cách cảm ơn người ghi bàn cao nhất được phân biệt rõ với người ghi bàn thấp nhất và sự khác biệt về tuổi của học sinh là thậm chí.

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.