Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 将引用计数合并到每个数据库表中是一个好主意吗?_Database_Database Design_Release - Fatal编程技术网

Database 将引用计数合并到每个数据库表中是一个好主意吗?

Database 将引用计数合并到每个数据库表中是一个好主意吗?,database,database-design,release,Database,Database Design,Release,从Objective-C开始,我习惯于引用计数/保留计数(相同的事情)。我喜欢这个概念,而且很简单 所以我想,为什么不把它应用到数据库中呢?问题是: 想象一下这些表格:用户、照片。用户可以拥有照片,用户可以喜欢自己或他人的照片,用户可以推荐照片。在任何情况下,都会创建对照片的引用 现在最大的问题是:假设我想扔掉任何不属于任何人的照片。因此,一张不属于任何用户、不受任何用户喜爱、也不被任何用户推荐的照片必须被删除。我不知道如何使用普通数据库功能做到这一点;)嗯,也许有几百人加入?我不知道。数据库n

从Objective-C开始,我习惯于引用计数/保留计数(相同的事情)。我喜欢这个概念,而且很简单

所以我想,为什么不把它应用到数据库中呢?问题是:

想象一下这些表格:用户、照片。用户可以拥有照片,用户可以喜欢自己或他人的照片,用户可以推荐照片。在任何情况下,都会创建对照片的引用

现在最大的问题是:假设我想扔掉任何不属于任何人的照片。因此,一张不属于任何用户、不受任何用户喜爱、也不被任何用户推荐的照片必须被删除。我不知道如何使用普通数据库功能做到这一点;)嗯,也许有几百人加入?我不知道。数据库noob

所以我想从DB专家那里验证一下这个想法:想象一下,我为每个可以被引用的表添加了一个reference_count字段(当然,在设置时需要一些考虑)。一旦我定义了从任何表_a到任何表_b的关系,并且表_a应该是父级或主级(强引用),我就将链接行的引用计数增加1

假设150个用户喜欢一张照片,其中一个拥有它。所以它的参考值是151。现在店主放弃了,但还有150人尖叫着“哦,不,不,不,不,不!!这是我们的!我们非常喜欢它!!”。系统每午夜查看所有这些表一次,并尝试删除引用计数为0的每一行。因此,过了几天,用户对它感到厌倦,并删除了他们的“我喜欢它”标志。每次发生这种情况时,引用计数都会减少1。最后,它是0,下一个午夜,当所有人都睡着时,cron作业会删除它

当然,它必须是可配置的,因为它不能总是在没有人引用照片后删除照片。我可以通过将它的reference_count初始设置为1而不是0来解决这个问题


我想,这当然意味着有很多额外的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
,并且不需要引用计数。

此问题通常通过使用

  • 支持孤立删除的ORM层,或
  • 删除孤立项的数据库触发器

  • 使用引用计数可能会很昂贵,具体取决于数据修改的频率,并且可能会使数据库代码变得晦涩难懂。

    我认为这就是级联删除的目的。我不赞成这样做。对于非垃圾收集语言来说,引用计数是一个好主意,但在本例中,我认为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约束,它会隐式地跟踪同一件事?我很困惑,为什么你会保留一张照片,而照片的所有者不再想要了?如果我试图删除一张照片却没有删除,我会非常生气。如果其他人喜欢它对我来说并不重要,我拥有版权,我不希望它出现在你的网站上。