2010-05-27 38 views
7

Tôi có một bảng lưu trữ nhận xét, nhận xét có thể đến từ một người dùng khác hoặc một tiểu sử khác là các thực thể riêng biệt trong ứng dụng này.Thực tiễn tốt nhất về cơ sở dữ liệu

suy nghĩ ban đầu của tôi là bảng sẽ có cả hai lĩnh vực user_id và PROFILE_ID, vì vậy nếu một người dùng gửi nhận xét, nó mang lại cho các user_id rời PROFILE_ID trống

là quyền này, sai, là có một cách tốt hơn ?

Trả lời

1

Trước đây tôi đã sử dụng bảng nhận xét tập trung và có trường cho fk_table mà nó đang tham chiếu.

ví dụ:

comments(id,fk_id,fk_table,comment_text) 

Bằng cách đó bạn có thể sử dụng các truy vấn UNION để nối dữ liệu từ nhiều nguồn khác nhau.

SELECT c.comment_text FROM comment c JOIN user u ON u.id=c.fk_id WHERE c.fk_table="user" 
UNION ALL 
SELECT c.comment_text FROM comment c JOIN profile p ON p.id=c.fk_id WHERE c.fk_table="profile" 

Điều này đảm bảo rằng bạn có thể mở rộng số đối tượng có nhận xét mà không tạo bảng dư thừa.

4

Nếu các ý kiến ​​là chung cho nhiều đối tượng bạn có thể tạo một bảng cho từng đối tượng:

user_comments (user_id, comment_id) 
profile_comments (profile_id, comment_id) 

Sau đó, bạn không cần phải có bất kỳ cột trống trong bảng bình luận của bạn. Nó cũng sẽ giúp bạn dễ dàng thêm các đối tượng nguồn nhận xét mới trong tương lai mà không cần chạm vào bảng bình luận.

+0

+ 1 cho kỹ thuật chuẩn hóa đúng cách – DancesWithBamboo

+0

Tôi thích giải pháp này nhưng thực hiện lọc đơn giản các nhận xét của người nhận xét hoặc loại người nhận xét sẽ yêu cầu tham gia. – cherouvim

+0

Thật vậy - nhưng sự tham gia là một nhược điểm nhỏ và luôn có thể tạo một Thủ tục xem hoặc lưu trữ để bạn không phải suy nghĩ về việc tham gia mỗi khi bạn cần lấy dữ liệu đó. – becquerel

3

Cách khác để giải quyết là luôn luôn chuẩn hóa (sao chép) tên của người nhận xét trên nhận xét và cũng lưu trữ tham chiếu về người nhận xét qua loại và trường id. Bằng cách đó bạn có một bảng bình luận thống nhất, nơi bạn có thể tìm kiếm, sắp xếp và cắt nhanh chóng. Nhược điểm là không có mối quan hệ FK thực sự nào giữa nhận xét và chủ sở hữu của nó.

+0

Trong số các phương pháp được đề cập đến nay, tôi thích phương pháp này. Vâng, không có mối quan hệ chính yếu ngoài nước; đó sẽ luôn là một nhược điểm ở đây, nhưng không nhiều ứng dụng web lo lắng về điều đó! Đây là cách mở rộng nhất mà không cần tạo nhiều bảng khác nhau để lưu trữ thông tin tương tự. –

+0

Tôi không hiểu. bạn đang nói, lưu trữ một bản sao của tên người bình luận nhưng không có FK? – Tim

+0

@ user270797: dữ liệu nhận xét đã có sẵn trên bảng. Dữ liệu của người nhận xét (tên, email, v.v.) phải được sao chép (không chuẩn hóa) trên bảng bình luận để dễ dàng truy cập. Giải pháp này có ý nghĩa trong một số trường hợp. – cherouvim

5

Bất cứ giải pháp nào tốt nhất đều phụ thuộc IMHO vào nhiều hơn chỉ là bảng, nhưng cũng làm thế nào điều này được sử dụng ở nơi khác trong ứng dụng.

Giả sử rằng các nhận xét đều được liên kết với một số đối tượng khác, giả sử bạn trích xuất tất cả các nhận xét từ đối tượng đó. Trong thiết kế được đề xuất của bạn, việc giải nén tất cả các bình luận chỉ cần chọn từ một bảng, đó là hiệu quả. Nhưng đó là trích xuất các nhận xét mà không cần trích xuất thông tin về áp phích của từng nhận xét. Có lẽ bạn không muốn hiển thị nó, hoặc có thể chúng đã được lưu trữ trong bộ nhớ.

Nhưng điều gì sẽ xảy ra nếu bạn phải truy xuất thông tin về người đăng khi truy xuất nhận xét? Sau đó, bạn phải tham gia với hai bảng khác nhau, và bây giờ tập hợp kết quả thu được ô nhiễm với rất nhiều giá trị NULL (cho một bình luận hồ sơ, tất cả các trường người dùng sẽ là NULL). Mã mà phải phân tích cú pháp tập kết quả này cũng có thể phức tạp hơn.

Cá nhân, tôi có lẽ sẽ bắt đầu với phiên bản hoàn toàn bình thường, và sau đó denormalize khi tôi bắt đầu thấy vấn đề hiệu suất

Ngoài ra còn có một giải pháp hoàn toàn khác nhau có thể cho vấn đề, nhưng điều này phụ thuộc vào việc hay không nó làm ý nghĩa trong miền. Điều gì xảy ra nếu có những nơi khác trong ứng dụng mà người dùng và người đăng có thể được sử dụng thay thế cho nhau? Điều gì sẽ xảy ra nếu Người dùng chỉ là một loại Hồ sơ đặc biệt? Sau đó, tôi nghĩ rằng giải pháp nên được giải quyết thường trong bảng người dùng/hồ sơ.Ví dụ: (một số pseudo-sql viết tắt):

create table AbstractProfile (ID primary key, type) -- type can be 'user' or 'profile' 
create table User(ProfileID primary key references AbstractProfile , ...) 
create table Profile(ProfileID primary key references AbstractProfile , ...) 

Sau đó, bất kỳ nơi nào trong ứng dụng của bạn có thể được sử dụng thay thế cho nhau, bạn có thể tham chiếu ID đăng nhập.

+1

+1 Đây là giải pháp mà tôi bắt đầu viết. Xem thêm * Hiệp hội đa hình * trong http://www.slideshare.net/billkarwin/practical-object-oriented-models-in-sql –

0

Dưới đây là cách tiếp cận khác, cho phép bạn để duy trì tính toàn vẹn tham chiếu thông qua các phím nước ngoài, quản lý tập trung, và cung cấp hiệu suất cao nhất sử dụng công cụ cơ sở dữ liệu tiêu chuẩn như chỉ số và nếu bạn thực sự cần, phân vùng vv:

create table actor_master_table(
    type char(1) not null, /* e.g. 'u' or 'p' for user/profile */ 
    id varchar(20) not null, /* e.g. 'someuser' or 'someprofile' */ 
    primary key(type, id) 
); 

create table user(
    type char(1) not null, 
    id varchar(20) not null, 
    ... 
    check (id = 'u'), 
    foreign key (type, id) references actor_master_table(type, id) 
); 

create table profile(
    type char(1) not null, 
    id varchar(20) not null, 
    ... 
    check (id = 'p'), 
    foreign key (type, id) references actor_master_table(type, id) 
); 

create table comment(
    creator_type char(1) not null, 
    creator_id varchar(20) not null, 
    comment text not null, 
    foreign key(creator_type, creator_id) references actor_master_table(type, id) 
); 
Các vấn đề liên quan