用户创建唯一标记时的表性能

时间:2013-10-08 22:29:47

标签: ruby-on-rails

在我的用户模型中,我有以下方法:

def confirmation_token
    self.confirmation = loop do
        random_token = SecureRandom.urlsafe_base64(16, false)
        break random_token unless User.exists?(confirmation: random_token)
    end
end

此方法只会创建一个随机令牌来确认用户的电子邮件......

你可以看到它在User.exists?(确认:random_token)时循环,这意味着它验证用户表中是否已有类似的令牌。

我的问题是:如果我在“用户表”中有很多行,我需要在此(确认)列中添加索引以获得更高的性能?

注意(此方法仅对每个用户执行一次......用户首次注册时)

2 个答案:

答案 0 :(得分:1)

是。如果您在任何特定列上执行了大量搜索(在本例中为confirmation),则应将该列编入索引。

答案 1 :(得分:0)

如果您只是按该值搜索,则会给您简短的答案。

虽然有一些事情需要考虑。首先,您可能希望该索引是唯一的,随着表的增长,这将大大提高性能。

add_index :users, :confirmation_token, unique: true

此外,您可能需要唯一值而不是随机值。虽然它不太可能产生重复,但它仍然是 random ,而不是唯一值。其中一个选项是使用某些用户列的Digest类生成和SHA,您知道该表对于此表是唯一的,如下所示:

Digest::SHA1.hexdigest(user.email)

UPD: Asker担心如果有人知道他使用电子邮件作为密钥并使用它来生成令牌的情况。

这通常是通过在加密前向电子邮件附加一些唯一键来解决的。您可以使用安全随机生成此类密钥并将其存储在环境变量中。 在.bashrc / .profile / .bash_profile或您使用的任何其他内容中,执行以下操作:

export EMAIL_TOKEN_SECRET="M9SyIuuOPhakX0b6gjvcRnsRHY="

然后这样做:

Digest::SHA1.hexdigest("#{user.email}-#{ENV['EMAIL_TOKEN_SECRET'}")