2012-05-01 63 views
5

Đây là một câu hỏi giả định hoàn toàn: giả sử tôi có một cơ sở dữ liệu nơi tôi cần lưu trữ tư cách thành viên cho người dùng, có thể kéo dài trong một khoảng thời gian cụ thể (1 tháng, 3 tháng, 6 tháng, 1 năm, v.v ...).Trong cơ sở dữ liệu, tốt hơn là lưu trữ một khoảng thời gian làm ngày bắt đầu/kết thúc, hoặc ngày bắt đầu và thời lượng?

Là nó tốt hơn để có một bảng Memberships có các trường (mỗi ngày được lưu trữ như một dấu thời gian unix):

user_id INT, start_date INT, end_date INT

hoặc để lưu trữ nó như:

user_id INT , start_date INT, length INT

Dù bằng cách nào, bạn có thể truy vấn người dùng có thành viên đang hoạt động hông (ví dụ). Đối với trường hợp thứ hai, số học sẽ cần phải được thực hiện mỗi khi truy vấn được chạy, trong khi tình huống trước đây chỉ yêu cầu ngày kết thúc được tính một lần (khi chèn). Từ quan điểm này, có vẻ như thiết kế cũ là tốt hơn - nhưng có bất kỳ hạn chế nào đối với nó không? Có bất kỳ vấn đề phổ biến có thể tránh được bằng cách lưu trữ chiều dài thay thế, mà không thể tránh được bằng cách lưu trữ ngày?

Ngoài ra, có phải dấu thời gian unix là con đường để đi khi lưu trữ dữ liệu thời gian/ngày hoặc là một cái gì đó như ưu tiên DATETIME không? Tôi đã chạy vào các vấn đề với cả hai kiểu dữ liệu (chuyển đổi quá mức) nhưng thường giải quyết trên dấu thời gian unix. Nếu một cái gì đó như DATETIME được ưa thích, làm thế nào điều này thay đổi câu trả lời cho câu hỏi thiết kế trước đây của tôi?

+0

Câu trả lời cho câu hỏi này có phụ thuộc vào hệ thống không? Cả hai giải pháp có vẻ tốt với tôi nhưng nếu không có truy vấn nào của bạn quan tâm đến thời lượng thì trường hợp đầu tiên sẽ tốt hơn. Nếu không, nó có thể là cách khác. Ngoài ra nếu bạn có truy vấn nặng sử dụng độ dài và truy vấn nặng sử dụng ngày kết thúc, bạn có thể muốn lưu trữ cả hai giá trị trong cơ sở dữ liệu của mình. –

Trả lời

2

Nó thực sự phụ thuộc vào loại truy vấn bạn sẽ chạy với ngày của bạn. Nếu truy vấn liên quan đến tìm kiếm theo thời gian bắt đầu/kết thúc hoặc phạm vi ngày sau đó bắt đầu/và ngày thì chắc chắn đi với tùy chọn đầu tiên.

Nếu bạn quan tâm nhiều hơn đến thống kê (Thời gian thành viên trung bình là bao nhiêu? Bao nhiêu người là thành viên trong hơn một năm?) Thì tôi đã chọn tùy chọn thứ 2.

Về chuyển đổi quá mức - bạn đang lập trình ngôn ngữ nào? Java/Ruby sử dụng Joda Time dưới mui xe và nó đơn giản hóa ngày/thời gian liên quan đến logic rất nhiều.

+0

+1 Bắt tốt về thống kê;) –

+0

Tôi nghĩ rằng sự kết hợp của câu trả lời này và Branko là tốt nhất, nhưng tôi chỉ có thể chấp nhận một ... Tôi sẽ cung cấp cho bạn vì đại diện của bạn thấp hơn. –

+0

Cuộc gọi tốt :-) lol –

0

Từ quan điểm thiết kế, tôi thấy thiết kế tốt hơn để có ngày bắt đầu và độ dài của tư cách thành viên.

Ngày kết thúc là một dẫn xuất của ngày bắt đầu thành viên + thời lượng. Đây là cách tôi nghĩ về nó.

1

Tôi sẽ không đồng ý. Tôi sẽ có một ngày bắt đầu và kết thúc - tiết kiệm thời gian thực hiện các phép tính.

1

Hai chiến lược có chức năng tương đương, chọn mục ưa thích của bạn.

2

Nếu phụ thuộc vào việc bạn muốn chỉ số ngày kết thúc, lần lượt phụ thuộc vào cách bạn muốn truy vấn dữ liệu.

Nếu bạn làm và nếu DBMS của bạn không hỗ trợ chỉ mục hoặc chỉ mục dựa trên chức năng trên cột được tính toán, thì truy vấn duy nhất của bạn là có số end_date thực để bạn có thể lập chỉ mục trực tiếp.

Ngoài ra, tôi không thấy nhiều sự khác biệt.

BTW, sử dụng kiểu ngày gốc mà DBMS của bạn cung cấp, chứ không phải int. Trước tiên, bạn sẽ đạt được một số biện pháp an toàn kiểu (vì vậy bạn sẽ gặp lỗi nếu bạn cố gắng đọc/ghi một int nơi ngày được mong đợi), ngăn bạn khỏi việc không khớp tính toàn vẹn tham chiếu (mặc dù các FK ngày tháng hiếm gặp) , nó có thể xử lý các múi giờ (tùy thuộc vào DBMS), DBMS thường sẽ cung cấp cho bạn các chức năng để trích xuất các thành phần ngày ...

+0

+1, nắm bắt tốt về chỉ số. –

0

Nếu thành viên có thể chuyển đổi theo thời gian tôi sẽ đề nghị tùy chọn này:

user_id INT, 
since_date DATE, 
active_membership BIT 

nơi tình trạng active_membership là những gì được toggled theo thời gian, và since_date được theo dõi khi điều này xảy ra. Hơn nữa, nếu bạn có tập hữu hạn có độ dài thành viên được phép và cần phải theo dõi trong đó chiều dài một người dùng nhất định đã chọn, điều này có thể được mở rộng để:

user_id INT, 
since_date DATE, 
active_membership BIT, 
length_id INT 

nơi length_id sẽ đề cập đến một bảng tra cứu của sẵn và cho phép độ dài thành viên. Tuy nhiên, xin lưu ý rằng trong trường hợp này, since_date trở nên mơ hồ nếu có thể thay đổi độ dài thành viên của bạn. Trong trường hợp đó, bạn sẽ phải mở rộng hơn nữa:

user_id INT, 
active_membership_since_date DATE, 
active_membership BIT, 
length_since_date DATE, 
length_id INT 

Với cách tiếp cận này, dễ dàng thấy rằng bình thường hóa sẽ bị hỏng khi hai ngày thay đổi không đồng bộ. Để giữ bình thường hóa bạn thực sự cần 6NF. Nếu yêu cầu của bạn đang đi theo hướng này, tôi sẽ đề nghị xem Anchor modeling.

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