如何在php/mysql中实现类似于SO的标记系统?

Mic*_* D. 1 php mysql tagging

我正在用PHP/MySQL编写一个网站,我想实现一个类似于stackoverflow标记引擎.我在DB中有3个相关表:1.项2.标签3. ItemTagMap(将标签映射到项目,n:n映射)

现在,在搜索页面上,我想显示整个搜索结果(不仅仅是当前页面)的所有标签的不同列表,以便用户可以通过添加/删除该标签列表中的标签来"优化"他们的搜索.

问题是,这是一个相当繁重的数据库查询,可能会有大量的搜索请求导致不同的结果集,从而导致不同的标记集.

有谁知道如何有效地实现这一点?

mjv*_*mjv 8

在我们进入过早优化模式之前,查看以下查询模板可能很有用.如果没有别的可以用作可以衡量可能优化的有效性的基线.

SELECT T.Tagid, TagInfo.TagName,  COUNT(*)
FROM Items I
JOIN Tags TagInfo ON TagInfo.TagId = T.TagId
JOIN ItemTagMap T  ON I.ItemId = T.ItemId 
--JOIN ItemTagMap T1 ON I.ItemId = T1.ItemId
WHERE I.ItemId IN
  (
      SELECT ItemId 
      FROM Items
      WHERE   -- Some typical initial search criteria
         Title LIKE 'Bug Report%'   -- Or some fulltext filter instead...
         AND  ItemDate > '02/22/2008'
         AND  Status = 'C'
  )
--AND T1.TagId = 'MySql'
GROUP BY T.TagId, TagInfo.TagName
ORDER BY COUNT(*) DESC
Run Code Online (Sandbox Code Playgroud)

子查询是"驱动查询",即对应于最终用户初始标准的查询.(有关此查询如何多次可能适合整体优化流程的详细信息,请参见下文)注释是T1上的JOIN(可能是T2,T3,当选择了多个标签时),并且,与WHERE子句相关联标准.当用户选择特定标签时,无论是作为初始搜索的一部分还是通过细化,都需要这些.(放置这些连接以及子查询中的where子句可能更有效;更多关于以下内容)

讨论...... 出于两个不同的目的,需要"驱动查询"或其变体:

  • 1提供枚举所有相关标签所需的ItemId 的完整列表.

  • 2,提供前N个ItemId值(N为显示页面大小),以便在Item表中查找Item详细信息.

请注意,完整列表不需要排序(或者它可能受益于以不同顺序排序),因此第二个列表需要根据用户的选择进行排序(例如按日期,降序或标题,按字母顺序升序).另请注意,如果需要任何排序顺序,查询的成本将意味着处理完整列表(不熟悉SQL本身的奇怪优化,和/或一些非规范化,SQL需要"看到"该列表上的最后记录,如果他们属于顶部,排序方式).

后一个事实,有利于为两个目的具有相同的查询,相应的列表可以存储在临时表中.一般流程是快速查找前N个项目记录及其详细信息,并立即将其返回给应用程序.然后,应用程序可以获得ajax-fashion标签列表以进行优化.此列表将使用类似于上面的查询生成,其中子查询由"select*from temporaryTable"替换.SQL优化器将决定对此列表进行排序(在某些情况下)的可能性很大,让我们让它做到这一点,而不是第二次猜测并明确地对其进行排序.

要考虑的另一点是,可以将ItemTagMap表中的连接带到"驱动查询"中,而不是如上所示.最好这样做,既可以提高性能,也可以为#2目的生成正确的列表(显示项目页面).

即使在相对适中的硬件上,上述查询/流程也可能相当好地扩展; 暂时进入1/2万+项目,持续的用户搜索可能达到每秒10次.其中一个关键因素是初始搜索标准的选择性.

优化的想法

  • [根据典型的搜索案例和数据统计],通过将一些Items的字段(实际上是复制的)带到ItemTagMap表来进行非规范化是有意义的.特别是短场可能在那里"欢迎".
  • 随着数据在百万+项目中的增长,我们可以利用一些标签的典型强相关性(例如:在SO中,PHP经常伴随MySql,通常没有充分的理由......),各种技巧.例如,"多标签"TagIds的引入可能使输入逻辑更复杂,但也可能显着减小Map大小.


- '够说!-
应根据实际要求和有效数据统计资料选择适当的架构和优化......