2009-07-14 35 views
77

Tôi lưu trữ các chi tiết người dùng khác nhau trong cơ sở dữ liệu MySQL của tôi. Ban đầu nó được thiết lập trong các bảng khác nhau có nghĩa là dữ liệu được liên kết với UserIds và xuất ra thông qua các cuộc gọi phức tạp đôi khi hiển thị và thao tác dữ liệu theo yêu cầu. Thiết lập một hệ thống mới, nó gần như hợp lý để kết hợp tất cả các bảng này thành một bảng lớn có nội dung liên quan.Cái nào hiệu quả hơn: Nhiều bảng MySQL hoặc một bảng lớn?

  • Đây có phải là trợ giúp hay cản trở không?
  • Cân nhắc tốc độ trong việc gọi, cập nhật hoặc tìm kiếm/thao tác?

Dưới đây là một ví dụ về một số cấu trúc của tôi bảng (s):

  • người dùng - UserId, tên người dùng, email, mật khẩu được mã hóa, ngày đăng ký, ip
  • user_details - dữ liệu cookie, tên, địa chỉ, thông tin liên lạc, liên kết, dữ liệu nhân khẩu học
  • user_activity - đóng góp, trực tuyến cuối cùng, xem cuối cùng
  • user_settings - hiển thị hồ sơ thiết lập
  • user_interests - biến nhắm mục tiêu quảng cáo
  • user_levels - quyền truy cập
  • user_stats - hits, trả khớp

Edit: Tôi đã bỏ phiếu tán tất cả các câu trả lời cho đến nay, tất cả họ đều có những yếu tố mà chủ yếu trả lời câu hỏi của tôi.

Hầu hết các bảng đều có mối quan hệ 1: 1 là lý do chính khiến chúng không chuẩn hóa chúng.

Sẽ có vấn đề gì nếu bảng trải dài trên hơn 100 cột khi một phần lớn các ô này có thể vẫn còn trống?

+0

[câu hỏi khác] này (http://stackoverflow.com/questions/8685621/what-is-the-best-database-schema-to-support-values-that-are-only-appropriate-to/9460541 # 9460541) có thể hữu ích quá –

Trả lời

47

Nhiều bảng giúp đỡ trong những cách/trường hợp sau đây:

(a) nếu những người khác nhau sẽ được phát triển các ứng dụng liên quan đến các bảng khác nhau, nó làm cho tinh thần để chia rẽ họ.

(b) Nếu bạn muốn cung cấp các loại quyền hạn khác nhau cho những người khác nhau cho một phần khác nhau của việc thu thập dữ liệu, việc phân chia dữ liệu có thể thuận tiện hơn. (Tất nhiên, bạn có thể xem xét định nghĩa lượt xem và cho phép chúng một cách thích hợp).

(c) Để di chuyển dữ liệu đến các địa điểm khác nhau, đặc biệt là trong quá trình phát triển, có thể có ý nghĩa khi sử dụng các bảng dẫn đến kích thước tệp nhỏ hơn.

(d) Bản in chân nhỏ hơn có thể mang lại sự thoải mái khi bạn phát triển các ứng dụng về thu thập dữ liệu cụ thể của một thực thể duy nhất.

(e) Đó là một khả năng: những gì bạn nghĩ là một dữ liệu giá trị duy nhất có thể trở thành nhiều giá trị thực sự trong tương lai. ví dụ. hạn mức tín dụng là một trường giá trị duy nhất kể từ bây giờ. Nhưng ngày mai, bạn có thể quyết định thay đổi các giá trị như (ngày, ngày, giá trị tín dụng). Bảng phân chia có thể có ích ngay bây giờ.

Phiếu bầu của tôi sẽ dành cho nhiều bảng - với dữ liệu được phân tách một cách thích hợp.

Chúc may mắn.

+1

Có nhiều bảng sẽ bị giảm hiệu suất không? –

+2

@RohitKhatri: Theo hiểu biết tốt nhất của tôi, có nhiều bảng sẽ tăng hiệu suất trong hầu hết các trường hợp. –

+1

@HariHarker Cảm ơn câu trả lời của bạn, nhưng tôi đã tìm ra rằng nó phụ thuộc vào mẫu truy cập của bạn. –

29

Kết hợp các bảng được gọi là không chuẩn hóa.

Có thể (hoặc có thể không) giúp thực hiện một số truy vấn (tạo nhiều số JOIN s) để chạy nhanh hơn với chi phí tạo địa ngục bảo trì.

MySQL chỉ có thể sử dụng phương pháp JOIN, cụ thể là NESTED LOOPS.

Điều này có nghĩa là đối với mỗi bản ghi trong bảng điều khiển, MySQL sẽ tìm một bản ghi phù hợp trong bảng được định hướng trong một vòng lặp.

Định vị bản ghi là hoạt động khá tốn kém, có thể mất hàng chục lần miễn là quét bản ghi thuần túy.

Di chuyển tất cả các bản ghi của bạn vào một bảng sẽ giúp bạn loại bỏ hoạt động này, nhưng bản thân bảng phát triển lớn hơn và quá trình quét bảng mất nhiều thời gian hơn.

Nếu bạn có nhiều bản ghi trong các bảng khác, thì tăng khả năng quét bảng có thể thừa hưởng lợi ích của các bản ghi được quét tuần tự.

Địa chỉ bảo trì, mặt khác, được đảm bảo.

+0

Nếu bạn có 10000 người dùng và bạn đang tham gia với một cơ sở dữ liệu được thiết lập với các khóa nước ngoài một cách chính xác thì bạn chỉ cần tra cứu dữ dội bằng cách thực hiện một cái gì đó như chọn * từ người dùng có tên = "bob" . Một khi bạn có bob sau đó bạn đang sử dụng một chỉ mục để tìm các bảng đã nối với bob nhanh hơn đáng kể bởi vì bạn đang sử dụng id của bob. Điều này xảy ra bất kể bạn đang tham gia vào truy vấn của bạn hay truy vấn bob sau đó truy vấn một bảng riêng biệt. Tất nhiên hy vọng truy vấn thứ hai của bạn dựa trên id của bob chứ không phải cái gì khác. –

6

Tạo một bảng lớn đi ngược lại các hiệu trưởng cơ sở dữ liệu quan hệ. Tôi sẽ không kết hợp tất cả chúng thành một cái bàn. Bạn sẽ nhận được nhiều trường hợp dữ liệu lặp lại. Ví dụ: nếu người dùng của bạn có ba sở thích, bạn sẽ có 3 hàng, với cùng một dữ liệu người dùng chỉ để lưu trữ ba sở thích khác nhau. Definatly đi cho phương pháp tiếp cận nhiều 'bình thường hóa' bảng. Xem this trang Wiki để chuẩn hóa cơ sở dữ liệu.

Edit: Tôi đã cập nhật câu trả lời của tôi, như bạn đã cập nhật câu hỏi của bạn ... Tôi đồng ý với câu trả lời ban đầu của tôi ngay cả bây giờ hơn vì ...

một phần lớn của các tế bào này là có thể vẫn còn trống

Nếu ví dụ, người dùng không có bất kỳ sở thích nào, nếu bạn bình thường thì bạn sẽ không có hàng trong bảng quan tâm cho người dùng đó. Nếu bạn có tất cả mọi thứ trong một bảng lớn, sau đó bạn sẽ có cột (và dường như rất nhiều trong số họ) có chứa chỉ NULL.

Tôi đã làm việc cho một công ty điện thoại nơi có rất nhiều bảng, việc nhận dữ liệu có thể yêu cầu nhiều lần tham gia. Khi hiệu năng đọc từ các bảng này là rất quan trọng thì các thủ tục được tạo ra có thể tạo ra một bảng phẳng (tức là một bảng không chuẩn hóa) sẽ không yêu cầu tham gia, tính toán vv mà các báo cáo có thể trỏ tới. Những nơi này sau đó được sử dụng kết hợp với một đại lý máy chủ SQL để chạy công việc tại các khoảng nhất định (tức là một lượt xem hàng tuần của một số số liệu thống kê sẽ chạy một lần một tuần và vv).

2

Tôi nghĩ đây là một trong những tình huống "phụ thuộc". Có nhiều bảng là sạch hơn và có lẽ về lý thuyết tốt hơn. Nhưng khi bạn phải tham gia 6-7 bảng để nhận thông tin về một người dùng, bạn có thể bắt đầu suy nghĩ lại cách tiếp cận đó.

8

Làm tất cả các bảng đó có mối quan hệ 1-to-1 không? Ví dụ: mỗi hàng của người dùng chỉ có một hàng tương ứng trong user_stats hoặc user_levels? Nếu có, có thể kết hợp chúng thành một bảng. Nếu mối quan hệ không phải là1 to 1, có thể sẽ không có ý nghĩa khi kết hợp (không chuẩn hóa) chúng.

Việc đặt chúng trong các bảng riêng biệt so với một bảng có thể sẽ có ít ảnh hưởng đến hiệu suất mặc dù trừ khi bạn có hàng trăm nghìn hoặc hàng triệu bản ghi người dùng. Việc đạt được thực sự duy nhất bạn sẽ nhận được là từ việc đơn giản hóa các truy vấn của bạn bằng cách kết hợp chúng.

ETA:

Nếu bạn mối quan tâm là về việc có quá nhiều cột, sau đó suy nghĩ về những thứ bạn thường sử dụng với nhau và kết hợp những, để lại phần còn lại trong một bảng riêng biệt (hoặc một vài riêng nếu cần).

Nếu bạn nhìn vào cách bạn sử dụng dữ liệu, tôi đoán rằng bạn sẽ thấy rằng 80% truy vấn của bạn sử dụng 20% ​​dữ liệu đó với 80% dữ liệu còn lại chỉ được sử dụng thỉnh thoảng. Kết hợp thường xuyên sử dụng 20% ​​vào một bảng, và để lại 80% mà bạn không thường xuyên sử dụng trong các bảng riêng biệt và có thể bạn sẽ có một sự thỏa hiệp tốt.

+0

Có mỗi bảng chỉ có 1 hàng cho mỗi người dùng, chỉ đơn giản là để lưu các nhức đầu của quản lý rất nhiều dữ liệu trùng lặp. Đây là lý do tại sao tôi đang nghĩ đến một bộ bàn. Nếu dữ liệu người dùng kéo dài nhiều hàng, tôi hy vọng sẽ có những bảng được tách ra khỏi bảng người dùng chính. –

+1

Nếu mỗi bảng có mối quan hệ 1 đến 1 thì một bảng sẽ dễ sử dụng hơn. Không cần phải chia bảng trong trường hợp đó. Tách các đại lý bảng có nhiều hơn 1 hàng, điều này có thể dẫn đến trường hợp một nhà phát triển khác đối xử với họ theo cách đó. –

1

Tôi sẽ nói điều đó phụ thuộc vào những gì các bảng khác thực sự có ý nghĩa. Có một user_details chứa nhiều hơn sau đó thêm 1/người dùng và vân vân. Mức độ chuẩn hóa phù hợp nhất với nhu cầu của bạn phụ thuộc vào nhu cầu của bạn.

Nếu bạn có một bảng có chỉ mục tốt có thể sẽ nhanh hơn. Nhưng mặt khác có lẽ khó khăn hơn để duy trì.

Đối với tôi, có vẻ như bạn có thể bỏ qua User_Details vì nó có thể là mối quan hệ 1-1 với Người dùng. Nhưng phần còn lại có thể là rất nhiều hàng cho mỗi người dùng?

16

Tất cả các mối quan hệ đó có phải là 1: 1 không? Ý tôi là, nếu người dùng có thể thuộc về cấp độ người dùng khác nhau hoặc nếu sở thích của người dùng được thể hiện dưới dạng một số bản ghi trong bảng sở thích của người dùng thì việc hợp nhất các bảng đó sẽ không nằm trong câu hỏi ngay lập tức.

Về câu trả lời trước về bình thường hóa, phải nói rằng các quy tắc chuẩn hóa cơ sở dữ liệu đã hoàn toàn bỏ qua hiệu suất và chỉ xem xét thiết kế cơ sở dữ liệu gọn gàng là gì. Đó thường là những gì bạn muốn đạt được, nhưng có những lúc nó có ý nghĩa để tích cực denormalize trong việc theo đuổi hiệu suất.

Tất cả trong tất cả, tôi muốn nói câu hỏi có bao nhiêu trường có trong bảng và tần suất chúng được truy cập. Nếu hoạt động của người dùng thường không thú vị, thì nó có thể chỉ là một mối phiền toái khi luôn có nó trên cùng một bản ghi, vì lý do bảo trì . Nếu một số dữ liệu, như cài đặt, nói, được truy cập rất thường xuyên, nhưng chỉ đơn giản là chứa quá nhiều trường, nó cũng có thể không thuận tiện để hợp nhất các bảng. Nếu bạn chỉ quan tâm đến hiệu suất, bạn có thể xem xét các cách tiếp cận khác, chẳng hạn như giữ các cài đặt riêng biệt, nhưng lưu chúng trong một biến phiên của riêng chúng để bạn không phải truy vấn cơ sở dữ liệu cho chúng rất thường xuyên.

+0

Tôi hoàn toàn không đồng ý với nhận xét của bạn rằng việc bình thường chỉ tập trung vào sự gọn gàng và hoàn toàn không quan tâm đến hiệu suất. Có một thương mại trong cả hai kịch bản và không chuẩn hóa thực sự đặt toàn vẹn dữ liệu vào rủi ro. Tôi sẽ nói bình thường hóa cơ sở dữ liệu của bạn thực sự cải thiện hiệu suất tổng thể của cơ sở dữ liệu thay vì có một sự gia tăng hiệu suất không đáng kể nhanh chóng từ một bảng không chuẩn hóa. –

6

Tại sao không sử dụng phương pháp tương tự Wordpress không bằng việc có một bảng cho người dùng với thông tin người dùng cơ bản mà mọi người đều có và sau đó thêm một "user_meta" bảng mà về cơ bản có thể được bất kỳ cặp khóa, giá trị liên kết với id người dùng. Vì vậy, nếu bạn cần tìm tất cả thông tin meta cho người dùng, bạn chỉ có thể thêm thông tin đó vào truy vấn của mình. Bạn cũng sẽ không phải luôn luôn thêm truy vấn phụ nếu không cần thiết cho những thứ như đăng nhập.Lợi ích của phương pháp này cũng khiến bảng của bạn mở rộng để thêm các tính năng mới cho người dùng của bạn như lưu trữ xử lý twitter của họ hoặc từng sở thích cá nhân. Bạn cũng sẽ không phải đối phó với một mê cung của ID được liên kết vì bạn có một bảng quy định tất cả siêu dữ liệu và bạn sẽ giới hạn chỉ một liên kết thay vì 50.

Wordpress thực hiện điều này để cho phép các tính năng được bổ sung thông qua các plugin, do đó cho phép dự án của bạn có khả năng mở rộng hơn và sẽ không yêu cầu đại tu cơ sở dữ liệu hoàn chỉnh nếu bạn cần thêm một tính năng mới.

+0

Bảng 'wp_usermeta' của Wordpress phát triển hình học. Mỗi người dùng thêm các hàng X vào bảng 'wp_usermeta', một hàng cho mỗi mẩu thông tin meta mà chúng tôi muốn giữ cho người dùng đó. Nếu bạn giữ 8 trường tùy chỉnh cho mỗi người dùng, điều đó có nghĩa là wp_usermeta sẽ là 'người dùng * 8' hàng dài. Điều này dường như đang gây ra các vấn đề về hiệu suất, nhưng tôi không chắc đó có phải là vấn đề hay không… – thirdender

+1

Tôi có thể thấy điều này có thể gây ra các vấn đề về hiệu năng nếu bạn có hàng chục nghìn người dùng. Về cơ bản, cơ sở dữ liệu sẽ phải tìm kiếm thông qua các mục 10000 * 8 trong bảng meta của người dùng để tìm những thứ mà bạn đang tìm kiếm. Tuy nhiên, nếu bạn chỉ truy vấn dữ liệu Meta khi cần tôi sẽ nghĩ hiệu suất của bạn sẽ tốt hơn. Nếu bạn luôn yêu cầu dữ liệu meta ngay cả khi bạn không cần nó thì bạn có thể gặp vấn đề. Nếu bạn luôn cần dữ liệu meta thì có thể tách các bảng không phải là cách tiếp cận tốt nhất. –

+1

Hôm qua chúng ta đã xử lý một chủ đề WP đang tải tất cả người dùng (sử dụng 'get_users()') chỉ để tính toán phân trang. Khi chúng tôi đã sửa mã để sử dụng truy vấn 'SELECT COUNT (…)' cho phân trang thay vào đó, thời gian tải trang đã tăng từ 28 giây lên khoảng 400ms. Tôi vẫn tự hỏi làm thế nào hiệu suất so sánh với các bảng đã tham gia hoặc một bảng phẳng đơn… Tôi đã gặp khó khăn trong việc tìm kiếm bất kỳ số liệu hiệu suất nào trên web. – thirdender

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