2008-08-21 30 views
244

Tôi đã nghe một số cách để triển khai gắn thẻ; bằng cách sử dụng bảng ánh xạ giữa TagID và ItemID (có ý nghĩa với tôi, nhưng nó có quy mô không?), thêm một số cột TagID có thể cố định vào ItemID (có vẻ như ý tưởng tồi), Giữ thẻ trong cột văn bản được phân cách bằng dấu phẩy (âm thanh điên rồ nhưng có thể làm việc). Tôi thậm chí đã nghe ai đó đề nghị một ma trận thưa thớt, nhưng sau đó làm thế nào để các tên thẻ phát triển một cách duyên dáng?Thiết kế cơ sở dữ liệu SQL được đề xuất cho thẻ hoặc gắn thẻ

Tôi có thiếu phương pháp hay nhất cho thẻ không?

+7

OK đây là câu hỏi # 20856, câu hỏi tương tự (gần như) là # 48475 được hỏi ít nhất hai tuần sau khi câu hỏi này được hỏi. – dlamblin

+6

Một câu hỏi thú vị khác là "Cách SO triển khai thẻ?" – Mostafa

+1

Một câu hỏi thú vị khác là "Bạn có quốc tế hoá chúng không, và nếu có thì làm thế nào?" – DanMan

Trả lời

353

Ba bảng (một để lưu trữ tất cả các mục, một cho tất cả các thẻ và một cho mối quan hệ giữa hai thẻ), được lập chỉ mục đúng cách, với bộ khóa nước ngoài đang chạy trên cơ sở dữ liệu thích hợp, hoạt động tốt và mở rộng.

Table: Item 
Columns: ItemID, Title, Content 

Table: Tag 
Columns: TagID, Title 

Table: ItemTag 
Columns: ItemID, TagID 
+10

Tôi không nghĩ rằng điều này có thể được upvoted đủ. Đây rõ ràng là cách tốt nhất để làm điều đó. – BobbyShaftoe

+98

Rõ ràng? Bằng chứng nào cho thấy đây rõ ràng là cách tốt nhất để làm điều này (ngoại trừ thực tế là nó được chuẩn hóa - còn, hãy nhớ bình thường hóa là chèn nhanh, chọn chậm). –

+0

Có bất kỳ tài liệu nào về phương pháp này không? Tôi tin rằng điều này cũng sẽ được biết ơn với các chỉ mục thay vì cột văn bản được phân cách bằng dấu phẩy – Cesar

7

Tôi luôn giữ các thẻ trong bảng riêng và sau đó có bảng ánh xạ. Tất nhiên tôi chưa bao giờ làm bất cứ điều gì trên một quy mô thực sự lớn.

Có bảng "thẻ" và bảng bản đồ làm cho nó trở nên tầm thường để tạo các đám mây thẻ & vì bạn có thể dễ dàng kết hợp SQL để nhận danh sách thẻ với tần suất sử dụng mỗi thẻ.

+1

Điều này thậm chí còn dễ dàng hơn nếu bạn không sử dụng bảng ánh xạ:) – Scheintod

11

Sử dụng cột văn bản được định dạng duy nhất [1] để lưu trữ thẻ và sử dụng công cụ tìm kiếm toàn văn có khả năng để lập chỉ mục này. Khác bạn sẽ chạy vào các vấn đề mở rộng quy mô khi cố gắng thực hiện các truy vấn boolean.

Nếu bạn cần thông tin chi tiết về các thẻ bạn có, bạn có thể theo dõi nó trong bảng được duy trì gia tăng hoặc chạy lệnh batch để trích xuất thông tin.

[1] Một số RDBMS thậm chí còn cung cấp loại mảng gốc có thể phù hợp hơn để lưu trữ bằng cách không cần bước phân tích cú pháp, nhưng có thể gây ra sự cố với tìm kiếm toàn văn.

+0

Bạn có biết bất kỳ công cụ tìm kiếm toàn văn nào không tìm thấy các biến thể trên một từ không? Ví dụ: tìm kiếm sách sẽ trả về sách? Ngoài ra, bạn làm gì về các thẻ như "C++"? Ví dụ, SQL Server sẽ loại bỏ các dấu cộng trong chỉ mục. Cảm ơn. –

+0

Hãy thử Sphinx - http://sphinxsearch.com – oyatek

+0

Hướng dẫn gồm 3 phần này có thể hữu ích cho những ai đang đi tuyến đường này (tìm kiếm toàn văn). Nó đang sử dụng các tiện ích gốc của PostgreSQL: http://shisaa.jp/postset/postgresql-full-text-search-part-1.html – Will

37

Nếu bạn đang sử dụng cơ sở dữ liệu hỗ trợ giảm bản đồ, như couchdb, lưu trữ thẻ trong trường văn bản thuần túy hoặc trường danh sách thực sự là cách tốt nhất. Ví dụ:

tagcloud: { 
    map: function(doc){ 
    for(tag in doc.tags){ 
     emit(doc.tags[tag],1) 
    } 
    } 
    reduce: function(keys,values){ 
    return values.length 
    } 
} 

Chạy ứng dụng này với nhóm = true sẽ nhóm kết quả theo tên thẻ và thậm chí trả về số lần thẻ đã gặp phải. Nó rất giống với counting the occurrences of a word in text.

+4

+1 Rất hay để xem một số triển khai NoSQL. – Xeoncross

+0

@NickRetallack Liên kết không hoạt động. Nếu có thể, vui lòng cập nhật câu trả lời này. – xralf

+0

Ok Tôi đã thay thế liên kết bằng một để lưu trữ.org –

57

Bình thường, tôi sẽ đồng ý với Yaakov Ellis nhưng trong trường hợp đặc biệt này còn có một giải pháp khả thi:

Sử dụng hai bảng:

Table: Item 
Columns: ItemID, Title, Content 
Indexes: ItemID 

Table: Tag 
Columns: ItemID, Title 
Indexes: ItemId, Title 

này có một số ưu điểm chính:

Đầu tiên nó làm cho phát triển đơn giản hơn nhiều: trong giải pháp ba bảng để chèn và cập nhật item bạn phải tra cứu bảng Tag để xem có mục nhập nào không. Sau đó, bạn phải tham gia với những người mới. Đây không phải là nhiệm vụ tầm thường.

Sau đó, truy vấn sẽ đơn giản hơn (và có thể nhanh hơn). Có ba truy vấn cơ sở dữ liệu chính mà bạn sẽ thực hiện: Xuất tất cả Tags cho một Item, vẽ Thẻ-Đám mây và chọn tất cả các mục cho một Tiêu đề Thẻ.

tất cả các Tag cho một Item:

3-Bảng:

SELECT Tag.Title 
    FROM Tag 
    JOIN ItemTag ON Tag.TagID = ItemTag.TagID 
WHERE ItemTag.ItemID = :id 

2-Bảng:

SELECT Tag.Title 
FROM Tag 
WHERE Tag.ItemID = :id 

Tag-Cloud:

3- Bảng:

SELECT Tag.Title, count(*) 
    FROM Tag 
    JOIN ItemTag ON Tag.TagID = ItemTag.TagID 
GROUP BY Tag.Title 

2-Bảng:

SELECT Tag.Title, count(*) 
    FROM Tag 
GROUP BY Tag.Title 

mục cho một Tag:

3-Bảng:

SELECT Item.* 
    FROM Item 
    JOIN ItemTag ON Item.ItemID = ItemTag.ItemID 
    JOIN Tag ON ItemTag.TagID = Tag.TagID 
WHERE Tag.Title = :title 

2-Bảng:

SELECT Item.* 
    FROM Item 
    JOIN Tag ON Item.ItemID = Tag.ItemID 
WHERE Tag.Title = :title 

Nhưng cũng có một số nhược điểm: Có thể mất nhiều không gian hơn trong cơ sở dữ liệu (có thể dẫn đến nhiều hoạt động đĩa chậm hơn) và không được chuẩn hóa mà có thể dẫn đến mâu thuẫn.

Đối số kích thước không phải là mạnh bởi vì bản chất của các thẻ là chúng thường nhỏ nên kích thước tăng không lớn. Người ta có thể cho rằng truy vấn cho tiêu đề thẻ nhanh hơn nhiều trong một bảng nhỏ chứa mỗi thẻ một lần và điều này chắc chắn là đúng. Nhưng lấy tiền tiết kiệm cho việc không phải tham gia và thực tế là bạn có thể xây dựng một chỉ số tốt trên chúng có thể dễ dàng bù đắp cho điều này. Điều này tất nhiên phụ thuộc rất nhiều vào kích thước của cơ sở dữ liệu bạn đang sử dụng.

Đối số không đồng nhất cũng là một chút tranh luận. Thẻ là trường văn bản miễn phí và không có hoạt động dự kiến ​​như 'đổi tên tất cả thẻ' foo 'thành' bar ''.

Vì vậy, tldr: Tôi sẽ đi cho giải pháp hai bảng. (. Trong thực tế tôi sẽ tôi tìm thấy bài viết này để xem nếu có đối số hợp lệ chống lại nó.)

+0

"Chỉ mục: ItemId, Tiêu đề" có nghĩa là chỉ mục cho mỗi hoặc một chỉ mục chứa cả hai không? – DanMan

+0

Thông thường hai chỉ mục. Có thể phụ thuộc vào cơ sở dữ liệu bạn đang sử dụng, mặc dù. – Scheintod

+1

Trong bảng thẻ là ItemId và Gắn thẻ một khóa tổng hợp? hoặc bạn có PK không? – Rippo

0

tôi sẽ đề nghị thiết kế sau: mục Bảng: Itemid, taglist1, taglist2
này sẽ được nhanh chóng và dễ dàng lưu và truy xuất dữ liệu ở cấp mục.

Xây dựng song song một bảng khác: Thẻ thẻ không tạo thẻ nhận dạng duy nhất và nếu bạn hết dung lượng trong cột thứ 2 chứa 100 mục, hãy tạo một hàng khác.

Bây giờ, trong khi tìm kiếm các mục cho thẻ, thẻ sẽ siêu nhanh.

+0

https://en.wikipedia.org/wiki/First_normal_form mặc dù có ngoại lệ cho điều này, bạn có thể không chuẩn hóa, nhưng không phải ở đây – Dheeraj

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