从Objective-C我习惯于引用计数/保留计数(同样的事情)。我喜欢这个概念,而且很简单。
所以我想,为什么不将它应用到数据库?问题是:
想象一下这些表:用户,照片。用户可以拥有照片,用户可以喜欢他自己或其他人的照片,并且用户可以推荐照片。无论如何,都会为照片创建一个参考。
现在最大的问题是:让我们说我想摆脱任何属于无人的照片。因此,不被任何用户拥有的照片不被任何用户所喜欢,并且不被任何用户推荐,必须被删除。我有没有想法如何使用普通的数据库功能;)好吧,可能有几百个连接?我不知道。数据库noob。
所以我想从数据库专家那里验证这个想法:想象一下我在每个可以引用的表中添加一个reference_count字段(当然需要一些设想)。一旦我定义了从table_a到任何table_b的关系,并且table_a应该是父或master(强引用),我将链接行的reference_count增加1。
假设150个用户喜欢照片,而其中一个拥有它。所以它的reference_count是151.现在主人放弃了,但是其他150人仍在尖叫“哦,不,不,不,不是!这是我们的!我们喜欢它如此muuucch !!”。系统通过所有这些表每隔午夜查看一次,并尝试删除引用计数为0的每一行。所以在几天之后,用户会对它感到厌倦并删除它们的“我喜欢它”标志。每次发生这种情况时,reference_count减少1.最后,它为0,并且在每个人都睡着的下一个午夜,一个cron作业删除它。
当然,它必须是可配置的,因为在没有人再引用照片之后必须永远不会删除照片。我会通过将它的reference_count最初设置为1而不是0来解决这个问题。
这当然意味着很多额外的db调用。所以你怎么看?或者有更好的解决方案吗?
答案 0 :(得分:4)
您可以执行以下操作:
DELETE
FROM photos
WHERE id NOT IN
(
SELECT photo_id
FROM photos_users_like
)
AND id NOT IN (
SELECT photo_id
FROM photos_users_made
)
AND id NOT IN (
SELECT photo_id
FROM photos_users_recommended
)
如果您在所有表中对photo_ids
编制索引,NOT IN
将由MySQL
进行优化,以便在引擎找到但是单个时谓词将返回FALSE
在相应的表中匹配记录,并且不需要引用计数。
答案 1 :(得分:3)
通常使用
解决此问题使用引用计数可能很昂贵,具体取决于数据修改的频率,并且可能会使您的数据库代码模糊不清,难以理解。
答案 2 :(得分:1)
您无需保留引用计数。我建议这样做。按照您的描述,您可以使用以下数据库结构:
create table users (
id int not null auto_increment
, name varchar(64) not null
...more columns...
, primary key (id)
)
create table photos (
id int not null auto_increment
, url varchar(255) not null
, user_id_owner int
, primary key (id)
, foreign key (user_id_owner) references users(id)
)
create table user_likes_photo (
user_id int not null
, photo_id int not null
, primary key(user_id, photo_id)
, foreign key (user_id) references users(id)
, foreign key (photo_id) references photos(id)
)
create table user_recommends_photo (
user_id_recommending int not null
, photo_id int not null
, user_id_recommended int not null
, primary key(user_id_recommending, photo_id, user_id_recommended)
, foreign key (user_id_recommending) references users(id)
, foreign key (user_id_recommended) references users(id)
, foreign key (photo_id) references photos(id)
)
这样,您可以跟踪所有关系。
要删除未提及的照片,请执行以下操作:
delete from photos
where user_id_owner is null
and id not in (
select photo_id
from user_likes_photo
)
and id not in (
select photo_id
from user_recommends_photo
)
答案 3 :(得分:1)
参考计数不一定是必要的;大多数数据库都会为您跟踪关系完整性
例如,如果你执行了
,则在ms-sql中delete from photos where photoid = 1234
但该照片在某处被引用,数据库将引发错误并拒绝删除照片;在.NET代码中,这表现为Sql异常
如果您需要提前知道是否可以删除照片,上述EXISTS查询将有效;如果你不需要事先知道,那就试着删除它,让数据库告诉你,你不能
引用计数是额外工作的很多,可能是不必要的;在这方面利用数据库的功能
答案 4 :(得分:0)
我认为这是级联删除的目的。我不赞成这样做。对于非垃圾收集语言,引用计数是一个好主意,但在这种情况下,我认为SQL已经覆盖了很长时间。
这就是拥有数据库管理员的好处。 Noobs往往会陷入困境。
答案 5 :(得分:0)
要查找没有人拥有的照片,您可以执行以下操作:
select P.PhotoId
from Photos as P
where not exist (select ownerId from PhotoOwners as PO where PO.PhotoId = P.PhotoId)
这可以扩展到任意数量的不存在检查。
为防止删除引用的照片,您可以使用外键。
总结:RDBMS旨在解决这些类型的问题,而无需引用计数和每个应用程序构建的其他(易出错)机制。
答案 6 :(得分:0)
无聊的用户不太可能不费力地扭转之前的upvote。为什么不计算一个更直接有用的指标,比如上个月的综合浏览量?
答案 7 :(得分:0)
“在这方面利用数据库的功能”
阿门。
并且其逻辑上的结论是“如果另一个DBMS在这方面具有更多功能,那么立即切换到该DBMS”。