我应该为联结表中的行使用唯一ID吗?

时间:2011-10-04 14:44:50

标签: sql tsql

我正在使用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列吗?在这种情况下,有没有更好的方法来查找随机记录?

以前的问题供参考

3 个答案:

答案 0 :(得分:2)

  1. NEWID足够随机,可能最好
  2. 10k行是花生
  3. 您不需要代理联结(链接,多人)表
  4. 的代理键

    编辑:如果你想过早地优化......

    您可以忽略这一点并从@Mitch Wheat中读取这些内容。但只有10k行,您的开发时间将比任何已保存的执行时间都长。

答案 1 :(得分:2)

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

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


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

我之所以这样说,是因为您提出的解决方案需要将()所有记录的NEWID()分配给所有记录以找到第一个记录。随着表格大小的增加,这种操作会增长,并且可能变得相对昂贵。它是否足够昂贵,值得优化取决于发生的其他事情,频率等等。

然而,如果有连续的连续唯一标识符,则可以选择MIN(id)和MAX(id)之间的随机值,然后选择值为out的SEEK。然而,所有价值都是连续的要求往往是一个限制因素;你永远不会被允许删除中间表中的值,例如......

要克服这个问题,并且根据索引,可能会找到以下方法。

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()的任何其他调用在随机时间执行它通常是完全合适的。

答案 2 :(得分:0)

考虑一下你有什么。

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

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

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

如果你担心的话,我会对你所拥有的解决方案感到满意,等待测试。

我一直使用order by newid()