您将如何设计数据库以支持以下标记功能:
理想情况下,使用单个SQL语句查找使用(至少)一组n个给定标记标记的所有项目.由于要搜索的标签数量以及任何项目上的标签数量未知且可能很高,因此使用JOIN是不切实际的.
有任何想法吗?
谢谢你到目前为止的所有答案.
但是,如果我没有弄错的话,给出的答案显示了如何对标签进行OR搜索.(选择包含一个或多个n标签的所有项目).我正在寻找一个有效的AND搜索.(选择所有包含所有n个标签的项目 - 可能还有更多.)
我在我的网站上实现了一个类似于stackoverflow使用的标记系统,我的问题是 - 什么是存储标记的最有效方法,以便可以搜索和过滤它们?
我的想法是这样的:
Table: Items
Columns: Item_ID, Title, Content
Table: Tags
Columns: Title, Item_ID
Run Code Online (Sandbox Code Playgroud)
这太慢了吗?有没有更好的办法?
我很想知道Stack Overflow的标记和搜索是如何构建的,因为它看起来效果很好.
如果我想要执行以下所有操作,那么什么是良好的数据库/搜索模型:
也许以标准化的形式存储标签是有意义的,但也可以作为空格分隔的字符串用于#2,#4和#3的目的.思考?
我听说它说Stack Overflow使用Lucene进行搜索.真的吗?我听过几个关于SQL优化的播客,但没有关于Lucene的内容.如果他们确实使用Lucene,我想知道有多少搜索结果来自Lucene,以及"钻取"标签云是否来自Lucene.
我开发了一个使用标签(关键词)的网站,以便对照片进行分类.现在,我在MySQL数据库中拥有的是一个具有以下结构的表:
image_id (int)
tag (varchar(32))
Run Code Online (Sandbox Code Playgroud)
每当有人标记图像(如果标记有效并且有足够的投票),它就会被添加到数据库中.我认为这不是最佳的做事方式,因为现在我有5000个带标签的图像,标签表有超过40000个条目.我担心这会开始影响性能(如果它还没有影响它).
我认为这个其他结构认为获取与特定图像相关联的标签会更快,但是当我想要获取所有标签或者最常用的标签时,它看起来很糟糕:
image_id (int)
tags (text) //comma delimited list of tags for the image
Run Code Online (Sandbox Code Playgroud)
有没有一种正确的方法可以做到这一点,或者两种方式都或多或少相同?思考?
在构建存储过程/查询时,是否可以/应该使用LIKE条件作为INNER JOIN的一部分?我不确定我问的是正确的,所以让我解释一下.
我正在创建一个过程,该过程将在包含文本的列中搜索要搜索的关键字列表.如果我坐在控制台,我会这样执行:
SELECT Id, Name, Description
FROM dbo.Card
WHERE Description LIKE '%warrior%'
OR
Description LIKE '%fiend%'
OR
Description LIKE '%damage%'
Run Code Online (Sandbox Code Playgroud)
但是,我在一个存储过程中进行"强类型"列表解析时,我捡到的一个技巧是将列表解析为表变量/临时表,将其转换为正确的类型,然后对该表执行INNER JOIN在我的最终结果集中.当向程序发送整数ID列表时,这很有用.我最终得到一个如下所示的最终查询:
SELECT Id, Name, Description
FROM dbo.Card
INNER JOIN @tblExclusiveCard ON dbo.Card.Id = @tblExclusiveCard.CardId
Run Code Online (Sandbox Code Playgroud)
我想用一个字符串列表来使用这个技巧.但是因为我正在寻找一个特定的关键字,所以我将使用LIKE子句.理想情况下,我认为我的最终查询看起来像这样:
SELECT Id, Name, Description
FROM dbo.Card
INNER JOIN @tblKeyword ON dbo.Card.Description LIKE '%' + @tblKeyword.Value + '%'
Run Code Online (Sandbox Code Playgroud)
这可能/推荐吗?
有没有更好的方法来做这样的事情?
我在条款的两端加上通配符的原因是因为卡片文本中使用了"archfiend","beast-warrior","direct-damage"和"battle-damage"术语.
我的印象是,根据性能,我可以使用我指定的查询,还是使用全文关键字搜索来完成相同的任务?
除了让服务器对我想要文本搜索的字段进行文本索引之外,还有什么我需要做的吗?
我有3个计划:
1,在问题表中:
question
------------------------------------
id title content ... tags
------------------------------------
1 aaa bbb ... tag1,tag2,tag3 (use , to split more tags)
Run Code Online (Sandbox Code Playgroud)
2,在标签表和拆分中:
tags
------------------------------------
id tag
------------------------------------
1 tag1,tag2,tag3 (use , to split more tags)
Run Code Online (Sandbox Code Playgroud)
3,在标签表中:
tags
------------------------------------
id tag
------------------------------------
1 tag1
2 tag2
3 tag3
Run Code Online (Sandbox Code Playgroud)
我认为计划3更好,但您的意见是什么?
这个实现的任何其他好主意?
谢谢您的帮助 :)
我有一个PHP Web应用程序,它使用MySQL数据库进行对象标记,其中我使用了标记结构作为此SO问题的答案.
我想实现一个标记层次结构,其中每个标记都可以有一个唯一的父标记.然后搜索父标签T将匹配T的所有后代(即T,父母为T的标签(T的子女),T的孙子等).
最简单的方法是在标签表中添加一个ParentID字段,其中包含标签父标签的ID,如果标签没有父标签则添加一些幻数.然而,搜索后代然后需要重复完整搜索数据库以找到每个"代"中的标记,我想避免这些标记.
一个(可能)更快,但更少规范化的方法是使用一个包含每个标记的所有子项的表,甚至每个标记的所有后代.然而,这会冒数据库中数据不一致的风险(例如,标签是多个父项的子项).
是否有一种很好的方法可以使查询快速查找后代,同时尽可能保持数据的标准化?
如何设计大型标签系统的数据存储(如digg或美味)?
已经讨论过它,但它是关于集中式数据库的.由于数据应该增长,我们需要很快或稍后将数据分区为多个分片.因此,问题变成:如何为分区标记系统设计数据存储?
标记系统基本上有3个表:
Item (item_id, item_content)
Tag (tag_id, tag_title)
TagMapping(map_id, tag_id, item_id)
Run Code Online (Sandbox Code Playgroud)
如果表存储在一个数据库实例中,那么找到给定标记的所有项并找到给定项的所有标记都可以.如果我们需要将数据分区为多个数据库实例,那就不那么容易了.
对于表项,我们可以使用其键item_id对其内容进行分区.对于表Tag,我们可以使用其key_id对其内容进行分区.例如,我们希望将表Tag分区为K个数据库.我们可以简单地选择数字(tag_id%K)数据库来存储给定的标签.
但是,如何分区表TagMapping?
该TagMapping表代表了许多一对多的关系.我只能想象有重复.也就是说,TagMappping的相同内容有两个副本.一个用tag_id分区,另一个用item_id分区.在为给定项找到标签的场景中,我们使用带有tag_id的分区.如果要查找给定标记的项目,我们使用带有item_id的分区.
结果,存在数据冗余.并且,应用程序级别应该保持所有表的一致性.看起来很难.
有没有更好的解决方案来解决这个多对多的分区问题?
我没有在4-5个月内接触到任何代码,所以今天回到它,通常需要一个星期左右的时间才能让我的大脑中的所有信息再次流过我的大脑.所以我即将开始的项目将是一个PHP/MySQL后端书签数据库.
我想用我最喜欢的网站/书签创建一个很好的可搜索数据库.每条记录都会分配多个关键字,因此我可以轻松地搜索所有书签中的"php",并且所有关键字列或标题中包含"php"的记录将返回到结果集中.
到目前为止,这是我对数据库的想法......
auto_id = /*Auto incremented ID number for database*/
name/title = /*Name/title of the Website*/
description = /*brief description of the site*/
URL = /*URL to open when I click a link*/
clicks = /*increments by 1 everytime I click the link*/
date_created = /*datetime that URL bookmark was added*/
date_accessed = /*datetime field for when last clicked on*/
category = /*category name or number to create a folder like structure of bookmarks in groups*/
sub_category = /*some …Run Code Online (Sandbox Code Playgroud) 编辑:建立标记系统的人.不读这个.这不是你想要的.当我不知道RDBMS都有自己的优化方法时,我问过这个,只需使用简单的多对多方案.
我有一个发布系统,有数百万的帖子.每个帖子都可以有无数个与之关联的标签.
用户可以创建具有注释,创建日期,所有者等的标签.标签几乎就像一个帖子本身,因为人们可以发布关于标签的注释.
每个标记关联都有一个所有者和日期,因此我们可以看到谁添加了标记以及何时添加.
我的问题是如何实现这一点?它必须通过标签快速搜索帖子,或通过邮寄标签.此外,用户可以通过在字段中键入名称来为帖子添加标签,有点像谷歌搜索栏,它必须为您填写标签名称的其余部分.
我目前有3个解决方案,但不确定哪个是最好的,或者是否有更好的方法.
请注意,我没有显示笔记的布局,因为一旦我得到适当的标签解决方案,这将是微不足道的.
方法1.链接列表
post中的tagId指向tag_assoc中的链表,应用程序必须遍历列表,直到flink = 0
post: id, content, ownerId, date, tagId, notesId
tag_assoc: id, tagId, ownerId, flink
tag: id, name, notesId
Run Code Online (Sandbox Code Playgroud)
方法2.非规范化
tags只是一个VARCHAR或TEXT字段,包含tagId:ownerId的制表符分隔数组.它不能是固定的大小.
post: id, content, ownerId, date, tags, notesId
tag: id, name, notesId
Run Code Online (Sandbox Code Playgroud)
方法3. Toxi
(来自:http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html,这里也是一样的:标签或标签的推荐SQL数据库设计)
post: id, content, ownerId, date, notesId
tag_assoc: ownerId, tagId, postId
tag: id, name, notesId
Run Code Online (Sandbox Code Playgroud)
方法3提出了一个问题,迭代tag_assoc中每一行的速度有多快?
方法1和2应该通过post快速返回标签,但对于按标签发布的帖子,必须另外创建一个查找表.
我不得不担心的最后一件事是按名称优化搜索标签,我还没有完成.
我在这里制作了一个ASCII图:http://pastebin.com/f1c4e0e53
tags ×9
database ×5
sql ×4
mysql ×3
tagging ×3
performance ×2
normalizing ×1
optimization ×1
partitioning ×1
php ×1
scalability ×1
sql-server ×1
structure ×1
tag-cloud ×1