Thiết kế cơ sở dữ liệu - Lưu trữ trạng thái hoặc trạng thái tính toán mỗi lần?


17

Giả sử tôi có một ứng dụng cơ sở dữ liệu quan hệ và một đối tượng "người dùng" và một đối tượng "tin nhắn". Bây giờ tôi muốn hiển thị số lượng tin nhắn chưa đọc cho người dùng này.

Cách tốt nhất để lưu trữ này là gì? Tôi có giới thiệu một trường trong người dùng và đếm nó nếu người dùng nhận được tin nhắn và giảm số đếm nếu anh ta đọc một trường không? Hoặc tôi có thực hiện truy vấn mỗi lần để tính số lượng tin nhắn cho người dùng được gắn cờ là chưa đọc không?

Tôi nghĩ cách tiếp cận thứ nhất phức tạp hơn và dễ bị lỗi hơn, nhưng sẽ thực hiện tốt hơn cách tiếp cận thứ hai.

Làm thế nào điều này thường được thực hiện hoặc cách tiếp cận tốt hơn?


1
Phụ thuộc vào một số yếu tố: DB của bạn có được phân vùng không? Có bao nhiêu hàng / người dùng mà bạn mong đợi? Tổng kích thước DB mà bạn mong đợi (hoặc có bao nhiêu tổng số người dùng)? Bạn mong đợi bao nhiêu yêu cầu mỗi giây? Tất cả những điều này không cần phải chính xác, nhưng một số ý tưởng sơ bộ ...
Omer Iqbal

10
+1 Đây là một câu hỏi cơ sở dữ liệu quan hệ cổ điển. Để bình thường hóa, hay không bình thường hóa? Đó là câu hỏi. Liệu họ có cao quý hơn trong lược đồ phải chịu đựng sự giằng xé và mũi tên của sự trùng lặp thái quá, hoặc chiếm lấy các tác nhân, và bằng cách sử dụng, kết thúc chúng?
Ross Patterson

Tôi tranh luận nếu đây là một mối quan hệ cổ điển. db. câu hỏi, đã có câu trả lời trên trang web, câu hỏi này nên được đóng lại dưới dạng DUP hoặc chúng tôi không có câu trả lời và điều này sẽ bị bỏ ngỏ.
mattnz

Câu trả lời:


14

Làm thế nào điều này thường được thực hiện hoặc cách tiếp cận tốt hơn?

Cách tiếp cận tốt nhất là thử nó trước mà không cần thêm trường, đo hiệu suất và nếu nó thực sự quá chậm, bạn cố gắng tối ưu hóa. Điều này có thể có nghĩa là chuyển sang cách tiếp cận đầu tiên của bạn bằng cách sử dụng một trường bổ sung, nhưng bạn cũng nên xem xét để kiểm tra các tùy chọn khác, ví dụ, đặt một chỉ mục bổ sung trên các trường kết hợp ("chưa đọc", "userID") trên tin nhắn của bạn.


2
Cách tiếp cận tốt nhất là (đi với phương pháp đơn giản hơn trước). Quy tắc chung là tốt hơn so với chi tiết cụ thể, fwiw. (+1 cho "kiểm tra!" Mặc dù.)
DougM

9

Giải pháp sách giáo khoa theo lý thuyết cơ sở dữ liệu sẽ không có giá trị trong cơ sở dữ liệu của bạn, phụ thuộc vào giá trị của dữ liệu khác, vì đây là các phụ thuộc bắc cầu . Có các trường được tính toán giá trị dựa trên các trường khác là vi phạm chuẩn hóa, vì nó dẫn đến thông tin dư thừa.

Tuy nhiên, đôi khi những gì sách giáo khoa nói và phương pháp thực tế nhất trong thực tế là khác nhau. Đếm số lượng tin nhắn chưa đọc mỗi lần xem trang có thể là một hoạt động khá tốn kém. Bộ nhớ đệm số trong user-table sẽ tốt hơn nhiều cho hiệu suất. Cái giá phải trả là có thể tồn tại sự không nhất quán trong cơ sở dữ liệu: Có thể tin nhắn sẽ bị xóa, thêm hoặc đọc mà không cần cập nhật bộ đếm chưa đọc.


4
Vấn đề nhất quán rất dễ xảy ra với các kích hoạt điều chỉnh bộ đếm trên INSERThoặc DELETE. (Hoặc UPDATE, để thay đổi chủ sở hữu của một tin nhắn thay đổi.). Một DBMS tốt sẽ thực hiện thao tác và chạy các kích hoạt trong cùng một giao dịch, vì vậy tất cả hoặc không có gì sẽ xảy ra.
Blrfl

4

Vấn đề tiềm năng là hiệu suất và bạn chưa có vấn đề về hiệu suất. Có rất nhiều điều bạn có thể làm tùy thuộc vào cơ sở dữ liệu lựa chọn để xử lý việc này trong giải pháp số 1: lập chỉ mục, phần cứng, bộ nhớ đệm, v.v ... Tất cả phụ thuộc vào tần suất người dùng cần để có được số lượng tin nhắn chưa đọc hiện tại. Nhiều lựa chọn trong số này không yêu cầu mã hóa tùy chỉnh ở phía ứng dụng, vì vậy bạn có thể thực hiện chúng với thay đổi mã hoặc rất ít. Làm cho nó dễ dàng hơn để phát triển với các ứng dụng.

Khi người dùng kết nối / đăng nhập, việc đếm số lượng từ cơ sở dữ liệu một lần không phải là xấu. Ứng dụng của bạn sẽ duy trì một danh sách cập nhật liên tục các tin nhắn như email chứ? Việc đếm số lượng chưa đọc từ đây không yêu cầu một chuyến đi khác đến cơ sở dữ liệu và để nhận được tin nhắn mới sẽ phải thực hiện một chuyến đi db.

Thực hiện một chuyến đi đến db mỗi khi đọc tin nhắn để gắn cờ IsRead? lĩnh vực này là đủ mà không cần tính toán lại một lĩnh vực khác.

Với giải pháp số 2 (giữ số đếm trong một trường / trên đĩa), bạn sẽ cần một thói quen để định kỳ xây dựng lại / tính toán lại trường này khi có vấn đề? Và luôn có vấn đề. Bạn sẽ bọc tất cả những điều này trong một giao dịch? Mỗi lần ai đó gửi tin nhắn cho người khác, nó có thể thất bại vì nó không thể cập nhật UnreadCount của người dùng đang nhận do khóa bảng Người dùng? Hay bạn sẽ tạo một bảng riêng cho lĩnh vực này?


+1 để đề cập đến các vấn đề về hiệu suất với việc giữ cho các trường đếm được cập nhật
nháy mắt vào

0

Cách tôi sẽ làm là bằng cách thực hiện một truy vấn mỗi lần, tức là cách tiếp cận thứ hai của bạn. Chỉ cần đảm bảo bạn thêm một chỉ mục trong bảng thông báo của bạn trên cột hoạt động như một khóa ngoại cho bảng người dùng để cải thiện hiệu suất truy vấn của bạn.

Sau đó, như Doc nói, đo lường hiệu suất của phương pháp này và sau đó bạn sẽ có thể biết liệu bạn có cần đi một con đường khác hay không.

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.