【问题标题】:Should I use a unique ID for a row in a junction table?我应该为联结表中的一行使用唯一 ID 吗?
【发布时间】:2011-10-04 14:44:50
【问题描述】:

我使用的是 SQL Server 2008。

不久前,我问了一个问题“我应该在联结表中使用 RecordID”。表格如下所示:

// Images
ImageID// PK

// Persons
PersonID // pk

// Images_Persons
RecordID // pk
ImageID // fk
PersonID // fk

强烈建议我不要使用 RecordID,因为它在两个 ID 创建唯一组合的表中没有用,这意味着不会有重复的记录。

现在,我正在尝试在联结表中找到一条随机记录来创建一个测验。我想拉第一个id,看看是否有人可以匹配第二个id。具体来说,我抓取了一张随机图像,并显示了三种可能的人选。

以下查询有效,但我有相当多的消极情绪表明它非常慢。我的数据库可能有 10,000 条记录,所以我认为这并不重要。我还读到生成的值并不是真正随机的。

SELECT TOP 1 * FROM Images_Persons ORDER BY newid();

我是否应该添加 RecordID 列?在这种情况下,有没有更好的方法来查找随机记录?

以前的问题供参考

【问题讨论】:

  • 这是完全有效的。
  • 您如何看待拥有 RecordID 字段将帮助您更有效地获得随机记录?
  • @Adrian 我也考虑过,但是只要RecordID 列是连续的,您就可以使用RAND。可能有点粗糙。

标签: sql tsql


【解决方案1】:
  1. NEWID 足够随机,可能是最好的
  2. 10k 行是花生
  3. 联结(链接,多对多)表不需要代理键

编辑:如果您想过早优化...

您可以忽略这一点并从@Mitch Wheat 阅读这些内容。但是只有 10k 行,您的开发时间将比任何节省的执行时间都长..

【讨论】:

    【解决方案2】:

    就我个人而言,我认为不应该建议使用 RecordID 列。相反,我建议它通常是不必要的。

    种情况下,使用单个值来标识行会使代码更简单。但它们是以额外存储为代价的,通常是额外的索引等。实际开销很小,但好处也是如此。


    在随机记录的选择方面,单个唯一标识符的存在可以使任务更容易如果标识符都是连续的和连续的。

    我这么说的原因是因为您提出的解决方案需要将 NEWID() 分配给 每个 记录,并且对 所有 记录进行排序以找到第一个记录。随着表大小的增长,此操作也会增长,并且可能变得相对昂贵。是否值得优化取决于发生的其他事情、频率等。

    但是,如果有连续的连续唯一标识符,则可以在 MIN(id) 和 MAX(id) 之间选择一个随机值,然后找出该值。然而,要求所有值都是连续的,这通常是一个过分的约束。例如,您永远不能删除中间表中的值...

    要克服这个问题,根据索引,您可能会发现以下方法很有用。

    DECLARE
      @max_id INT
    SELECT
      @id = COUNT(*)
    FROM
      Images_Persons
    
    SELECT
      *
    FROM
    (
      SELECT
        *,
        ROW_NUMBER() OVER (ORDER BY ImageID, PersonID) AS id
      FROM
        Images_Persons
    )
      AS data
    WHERE
      Images_Persons.id = CAST(@max_id * RAND() + 1 AS INT)
    
    -- Assuming that `ImageID, PersonID` is the clustered index.
    

    这里的缺点是 RAND() 在真正随机方面是出了名的差。然而,如果在相对于任何其他 RAND() 调用的随机时间执行,它通常非常合适。

    【讨论】:

    • CAST(@max_id * RAND(CHECKSUM(NEWID())) + 1 AS INT) 我比较随意。但我不是统计学家,所以我会让其他人对此发表评论......
    • 这样比较好,因为你在PK上找
    【解决方案3】:

    想想你有什么。

    SELECT TOP 1 * FROM Images_Persons ORDER BY newid();
    

    不是真正随机的吗?排除“真正随机是不可能的”位,您可能是对的 - 我相信生成的唯一标识符中存在模式。但是你应该自己测试一下。这很简单;只需创建一个包含 1 到 100 的表,order by newid() 很多次,然后查看结果。如果它对您来说随机“足够”(对于测验来说可能是这样),那么它就足够了。

    很慢?我不会担心的。如果newid() 比从表中读取记录慢,我会感到非常惊讶。但同样,测试和基准测试。

    如果您对此感到担忧,我会对您拥有的解决方案感到满意,正在等待测试。

    我一直用order by newid()

    【讨论】:

    • 感谢您的意见。我只是不熟悉所涉及的所有问题。这条线似乎很简单是正确的。
    猜你喜欢
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多