关于“tag标签”的实现问题(顺请foolbirdflyfirst兄接分)

wasuka 2007-07-27 03:22:58
搜寻了很久tag的解决方案,一直没有一种最好的办法。
今日和foolbirdflyfirst兄探讨了一下,以下两种方法可能是能想到的最好的,请大家提提意见,谢谢。

===============================================================
方法一:

create table article
(
ID int...
tag varchar(255),
index (tag)
);

create table tag
(
ID int...
tag varchar(10),
primary key (ID),
unique (tag)
)

文章表中的tag字段用来存放tag的ID的列表,用“,”分隔,例如“1,2,3”。

===============================================================
方法二:

create table article
(
ID int...
);

create table tag
(
ID int...
tag varchar(10),
primary key (ID),
unique (tag)
)

create table tag_relation
(
ID int...
ArticleID int,
TagID int,
INDEX (ArticleID),
INDEX (TagID)
);

tag关系表中,ArticleID与TagID是1对n的关系,既如果1篇文章有3个tag,那么表中就有3条数据。

=================================================================

方法1的优势在于节省了大量的空间,但是按tag搜索的时候只能用FIND_IN_SET(),这样索引就不能生效了,即使加上”force index”也不行;
方法2的优势在于能够使用索引,加快搜索速度,但是空闲开销巨大,表内会有articles×article.tags条记录。

想请教大家的是:对于第1种方法,有没有优化方案使得查询tag时效率更高?两种方法有没有更优化的方案?除了上述两种方法,还有没有更好的方法?

谢谢大家
...全文
1081 36 打赏 收藏 转发到动态 举报
写回复
用AI写文章
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
knifewolf88 2008-07-23
  • 打赏
  • 举报
回复
mark,以后来看看
chaircat 2007-08-05
  • 打赏
  • 举报
回复
看了整贴...
发表点愚见...
没做过大项目...
不知道这样到底有多大影响...
不过我想ls的方法可以cache各个tag的数目来满足效率...
设置个更新cache的机制(定时,手动随便)应该没问题...
wasuka 2007-07-31
  • 打赏
  • 举报
回复
这样的话,如果需要按照出现次数排序tag就不方便了
ImN1 2007-07-30
  • 打赏
  • 举报
回复
你搞错了

其实是一个tag只有一条记录
tag table
tag:value
"PHP":17653,12468……
"WEB2.0":17653,19472,20356……
(必要时可以加入字段——文章标题,思路要换一下)

搜索"PHP"得到17653,12468……(只有一条记录啊),然后交给php数组函数处理,获得每篇文章的id,然后进行二次搜索

另外,你不是打算把上万个文章的标题都列在同一个html吧?
所以二次搜索最多只是数百条而已

虽然两次或多次搜索,但中间限定的条件很明确,搜索的记录数量也不大
比起用一条sql全部搜索出来要好得多

wasuka 2007-07-28
  • 打赏
  • 举报
回复
SQL: select * from article where tag_id like '%[tag_id]%'and user_id='user_id'
-------------------------------------------------------------------------------
这样肯定不行啊,like '%**%'是不能使用索引的
helloyou0 2007-07-28
  • 打赏
  • 举报
回复
显然方法2好

tag_relation表只有3个字段,而且都是整形,所以占用空间并不过分,带来的速度上的优势和代码的简洁易懂就不是第一种能比的,
而且如果将来需求有改动时,方法2要灵活得多,更容易作修改。
zzmsl 2007-07-28
  • 打赏
  • 举报
回复
方案2的表结构好一点。
wasuka 2007-07-28
  • 打赏
  • 举报
回复
$article["tags"]=array(1,3,5,7……);
------------------------------------
按tag搜索文章的时候,SQL怎样写?

$tag["article"]=array(17653,12468……);
------------------------------------------
如果一个tag非常热门,引用次数达万次以上,那这个字段检索起来应该就很慢了
wwx840723 2007-07-28
  • 打赏
  • 举报
回复
为了避免yseet兄的担忧,所以我才想到tag_id这个入库方式。
wwx840723 2007-07-28
  • 打赏
  • 举报
回复
今天继续讨论,昨天走的太急了,也许么说清楚,我是这样做的
先有tag_id=1的,对应tag名是风景,在tag表中查询风景的纪录(完全匹配),得到tag_id和用户id,然后再在文章表中查询,
SQL: select * from article where tag_id like '%[tag_id]%'and user_id='user_id'


我注不同的是tag_id入库和tag表多个字段:用户ID;
wasuka 2007-07-28
  • 打赏
  • 举报
回复
直接把中文存进去,比如"美女,mm,K歌", 搜索的时候就方便多了
------------------------------------------------------------------
能否详细的说一下采用哪种“搜索”方式?效率如何?
yseet 2007-07-28
  • 打赏
  • 举报
回复




第一种的缺点是:如果用户搜索标题的时候,要把tag也应该搜到,这时候你就麻烦了.那怕组合sql语句, 搜索4的时候,可是4,41,14都会出来.当然,


我的做法是:

article表
id,
title,---标题之类的
tag varchar(200)

直接把中文存进去,比如"美女,mm,K歌", 搜索的时候就方便多了.


其实这问题是考虑用户需求,通常我的做法就是上面那种,网上常见的结果也是搜索的时候,是连tag字段也一起搜(方法是否一样就不知道了).



tag在article表中直接存放实际的内容就行了,将来可能还有其它附加功能要考虑.
ImN1 2007-07-28
  • 打赏
  • 举报
回复
本人不太懂数据库及其优化,但对这个问题说些个人的看法

1.这是一个“多对多”的问题,一个tag对应多篇文章,一篇文章也对应多个tag
2.这也是一个“无级分类”的问题,tag本身就是分类
ps:“无级分类”不等于“无限级分类”!!
3.tag和文章都是变化的,不能永久固定两者的relationship
4.tag < article(字串长度)

很显然,除非一早就把tag指定,否则难免在文章增加的时候会出现新的tag
也就是上面3所讲的问题

我倾向是方法1增加字段
$article["tags"]=array(1,3,5,7……);
$tag["article"]=array(17653,12468……);
因为查询是双向的,所以两个表都应该有"relationship"

在文章入库的时候,更新tag表,把article_id增加到相关tag的记录里面
增加新的tag的时候也做一次全article表的更新(涉及的文章)

没必要用“1文章对1tag的做一个记录”方式(1文章含n个tag=n个记录)

php的数组函数处理功能很强大的,结合位运算(包括sql的位运算)查询很方便的

web查询一般都是使用limit,输出只是几十至上百条数据,所以,没必要考滤一次全部查出
反而应该考虑组合多次查询优化最终查询的SQL语句更好
这个个人觉得和桌面程序是很大区别的
dotnet_boy 2007-07-27
  • 打赏
  • 举报
回复
先顶 看高人

--------------------
http://www.qiyesucha.com
wasuka 2007-07-27
  • 打赏
  • 举报
回复
InnoDB表
willko 2007-07-27
  • 打赏
  • 举报
回复
可以用全文索引。。。~~
但是容量很大
wasuka 2007-07-27
  • 打赏
  • 举报
回复
“like '1%'”和“like '%1%'”的差别是巨大的,后者不能使用索引
foolbirdflyfirst 2007-07-27
  • 打赏
  • 举报
回复
like是用不了索引的.数据量一大,效率是个问题.
wwx840723 2007-07-27
  • 打赏
  • 举报
回复
只是我个人的做法,不知道有什么不妥,因为我的项目也没做完
wwx840723 2007-07-27
  • 打赏
  • 举报
回复
表结构已经贴出来了,查询语句:where tag_id like '%[1]%'
加载更多回复(16)

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧