• Shopee đêm nay có mã cho ngày 5/5

thắc mắc Thiết kế database với mối quan hệ N-N

Như tiêu đề, em có 1 chút thắc mắc về việc thiết kế 2 table trong database về mối quan hệ N-N, mong mấy bác giúp giải đáp với ạ.

Cách 1: Thiết kế truyền thống là tạo 1 bảng chung rồi nối khóa ngoại của 2 bảng vào.
Cách 2: Ở table B thì tạo 1 cột lưu danh sách ID của table A. Ví dụ: trong ảnh, hơi sơ sài nhưng ý tưởng là như vậy
1681781590130.png


Thì em muốn hỏi là trong 2 cách thì cách nào ok hơn vậy ạ? Và các bác có thể cho em biết mặt tốt - xấu của 2 cách trên được không?
Tại em thì em ưu tiên về cách 2 hơn tại thấy nó khá easy.
 
Ví dụ nhỏ ở chức năng remove user from card:
  • Theo cách 1: chỉ cần drop or set null ở table mapping.
  • Theo cách 2: phải update 2 colunms "users" , "cards" à b?
Cứ theo truyền thống mà triển thôi b ơi :v
 
cái này nó có bài bản là dùng bản nối rồi, nếu ko có lý do gì đặc biệt như tối ưu lưu trữ, tốc độ và chấp nhận đánh đổi với 1 số vấn đề khác mới đem ra thảo luận thôi
 
Cách 1.

Còn cách 2 sao code được cascade, (ví dụ delete parent thì phải delete hết đống child)?
Rồi lúc delete, update child table, query sẽ rất chậm.
 
thế nếu quan hệ có thêm thuộc tính thì bác định lưu kiểu gì ? Cái gì là nguyên tắc thì đừng phá vỡ
 
Làm cách 1 nhé để tận dụng index khi search. Làm cách 2 mà query tìm user có card.id trong đoạn [1,2,3,4...n] thì biết mặt nhau ngay :look_down:
Em chào bác, bác có thể giải thích thêm tại sao lại biết mặt nhau được không ạ, em dân trái ngành nên muốn học hỏi thêm, mong bác giúp đỡ.
 
Em chào bác, bác có thể giải thích thêm tại sao lại biết mặt nhau được không ạ, em dân trái ngành nên muốn học hỏi thêm, mong bác giúp đỡ.
Giả sử cái bảng nối là user_card và list card_id cần tìm của bạn là
X = [1,2,3,4,...]
đặt x = X.length

Cách 1: viết 1 query xong luôn
SQL:
select user_id from user_card
where card_id in X
group by user_id
having count(card_id) = x

Cách 2:
SQL:
select users from cards where id in X
merge x list users kể trên

Cái cách 2 ở đây là lúc query nó phải read 1 lượng cực lớn data, chưa kể đoạn merge còn có thể ko tối ưu. Viết cách 1 hơn nữa database engine nó tối ưu hộ luôn, reduce được disk read nhiều với ko cần thao tác thêm ở ngoài.
Ngoài ra thì cách 2 còn nhiều nhược điểm như mấy bác kia nói ở trên: insert/delete card thì phải update lại đống user, inconsistent giữa mấy cái list (user chứa card mà card.users lại ko có user),...
Sơ sơ thì mình thấy như thế :big_smile:
 
Giả sử cái bảng nối là user_card và list card_id cần tìm của bạn là
X = [1,2,3,4,...]
đặt x = X.length

Cách 1: viết 1 query xong luôn
SQL:
select user_id from user_card
where card_id in X
group by user_id
having count(card_id) = x

Cách 2:
SQL:
select users from cards where id in X
merge x list users kể trên

Cái cách 2 ở đây là lúc query nó phải read 1 lượng cực lớn data, chưa kể đoạn merge còn có thể ko tối ưu. Viết cách 1 hơn nữa database engine nó tối ưu hộ luôn, reduce được disk read nhiều với ko cần thao tác thêm ở ngoài.
Ngoài ra thì cách 2 còn nhiều nhược điểm như mấy bác kia nói ở trên: insert/delete card thì phải update lại đống user, inconsistent giữa mấy cái list (user chứa card mà card.users lại ko có user),...
Sơ sơ thì mình thấy như thế :big_smile:
Là tức là nó đã phải scan từng row rồi, mỗi row nó lại phải scan x lần cái list nữa nên nó chậm phải không ạ?

Còn đối với cách 1 vì nó có bảng chung nên chỉ cần đánh index rồi search phát là ra phải không ạ.
 
Back
Top