Database 将引用计数合并到每个数据库表中是一个好主意吗?
从Objective-C开始,我习惯于引用计数/保留计数(相同的事情)。我喜欢这个概念,而且很简单 所以我想,为什么不把它应用到数据库中呢?问题是: 想象一下这些表格:用户、照片。用户可以拥有照片,用户可以喜欢自己或他人的照片,用户可以推荐照片。在任何情况下,都会创建对照片的引用 现在最大的问题是:假设我想扔掉任何不属于任何人的照片。因此,一张不属于任何用户、不受任何用户喜爱、也不被任何用户推荐的照片必须被删除。我不知道如何使用普通数据库功能做到这一点;)嗯,也许有几百人加入?我不知道。数据库noob 所以我想从DB专家那里验证一下这个想法:想象一下,我为每个可以被引用的表添加了一个reference_count字段(当然,在设置时需要一些考虑)。一旦我定义了从任何表_a到任何表_b的关系,并且表_a应该是父级或主级(强引用),我就将链接行的引用计数增加1 假设150个用户喜欢一张照片,其中一个拥有它。所以它的参考值是151。现在店主放弃了,但还有150人尖叫着“哦,不,不,不,不,不!!这是我们的!我们非常喜欢它!!”。系统每午夜查看所有这些表一次,并尝试删除引用计数为0的每一行。因此,过了几天,用户对它感到厌倦,并删除了他们的“我喜欢它”标志。每次发生这种情况时,引用计数都会减少1。最后,它是0,下一个午夜,当所有人都睡着时,cron作业会删除它 当然,它必须是可配置的,因为它不能总是在没有人引用照片后删除照片。我可以通过将它的reference_count初始设置为1而不是0来解决这个问题Database 将引用计数合并到每个数据库表中是一个好主意吗?,database,database-design,release,Database,Database Design,Release,从Objective-C开始,我习惯于引用计数/保留计数(相同的事情)。我喜欢这个概念,而且很简单 所以我想,为什么不把它应用到数据库中呢?问题是: 想象一下这些表格:用户、照片。用户可以拥有照片,用户可以喜欢自己或他人的照片,用户可以推荐照片。在任何情况下,都会创建对照片的引用 现在最大的问题是:假设我想扔掉任何不属于任何人的照片。因此,一张不属于任何用户、不受任何用户喜爱、也不被任何用户推荐的照片必须被删除。我不知道如何使用普通数据库功能做到这一点;)嗯,也许有几百人加入?我不知道。数据库n
我想,这当然意味着有很多额外的db调用。那你觉得呢?或者有更好的解决方案吗?您可以执行以下操作:
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
)
如果在所有表中为您的
照片ID
编制索引,NOT IN
s将通过MySQL
进行优化,这样当引擎在相应的表中只找到一条匹配记录时,谓词将返回FALSE
,并且不需要引用计数。此问题通常通过使用
使用引用计数可能会很昂贵,具体取决于数据修改的频率,并且可能会使数据库代码变得晦涩难懂。我认为这就是级联删除的目的。我不赞成这样做。对于非垃圾收集语言来说,引用计数是一个好主意,但在本例中,我认为SQL已经涵盖它很长时间了
这就是为什么有一个数据库管理员在场是件好事。Noobs往往会给自己带来麻烦。要找到没有人拥有的照片,您可以执行以下操作:
select P.PhotoId
from Photos as P
where not exist (select ownerId from PhotoOwners as PO where PO.PhotoId = P.PhotoId)
这可以扩展到任意数量的不存在性检查
要防止删除引用的照片,可以使用外键
摘要:RDBMS旨在解决这些类型的问题,而无需每个应用程序都建立引用计数和其他(容易出错的)机制。无聊的用户不太可能费劲地逆转他们以前的升级投票。为什么不计算一个更直接有用的指标,比如上个月的浏览量?您不需要保留引用计数。我劝你不要这样做。根据您的描述,您可以使用以下数据库结构:
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
)
参考计数不应该是必要的;大多数数据库都会为您跟踪关系完整性 例如,在ms sql中,如果执行
delete from photos where photoid = 1234
但是,该照片被引用在某个地方,数据库将引发错误并拒绝删除该照片;在.NET代码中,这表现为Sql异常
如果您需要提前知道是否可以删除照片,上述现有查询将起作用;如果你不需要事先知道,那么就试着删除它,让数据库告诉你你不能
引用计数是一项大量的额外工作,可能是不必要的;利用数据库在这方面的功能“利用数据库在这方面的功能”
阿门
同时也符合其逻辑结论,“如果另一个DBMS在这方面有更多的功能,那么立即切换到该DBMS。”看起来很有希望!这是标准的SQL,还是特定于特定的数据库?是的,这是标准的
SQL
,所有主要引擎都对其进行了很好的优化。请参见此处:MySQL
,并浏览以前的文章以了解其他引擎。+1。外键执行OP需要的操作。它们可以配置为,如果违反外键约束,则强制删除失败,或者也可以导致删除级联到依赖表(例如,您可以让它自动删除您喜欢的行和推荐行)我很困惑,为什么你不使用db约束,它会隐式地跟踪同一件事?我很困惑,为什么你会保留一张照片,而照片的所有者不再想要了?如果我试图删除一张照片却没有删除,我会非常生气。如果其他人喜欢它对我来说并不重要,我拥有版权,我不希望它出现在你的网站上。