我有一个包含数百万封电子邮件ID记录的注册表。电子邮件ID是唯一的。索引它们并使用asp.net获取它们以进行身份验证的最佳方法是什么?我的意思是我应该将电子邮件ID列定义为集群唯一索引而不是UNIQUE?
答案 0 :(得分:3)
如果您有一个可变长度的文本输入,例如电子邮件或地址,但您希望它们是唯一的,那么标准方法是索引该值的哈希。
原因:哈希是固定长度的,您可以避免文本数据超出索引长度的问题。
根据您的评论,您所拥有的表格看起来像这样(我故意省略密码和手机号码):
create table users (
user_id int not null unsigned auto_increment,
first_name varchar(255) not null,
surname varchar(255) default null,
email varchar(255) not null,
primary key(id)
) engine = innodb;
我会更改该表并添加包含电子邮件哈希的字段。我通过触发器维护它,以便您可以专注于获取有效数据,而无需担心创建哈希值。为此,该字段将为binary(20)
,因为它将包含原始哈希并占用20个字节。由于我们希望通过触发器维护它,因此我们需要使该字段可以为空且唯一。注意:您可以将其设为binary(40)
表:
create table users (
user_id int not null unsigned auto_increment,
email_hash binary(20) default null, -- this is the field in question
first_name varchar(255) not null,
surname varchar(255) default null,
email varchar(255) not null,
primary key(id),
unique(email_hash) -- this is the unique index over the hash
) engine = innodb;
我们现在需要的是处理电子邮件哈希的触发器。我将展示如何在插入之前创建保持此信息的触发器。类似的逻辑适用于更新表:
DELIMITER $$
CREATE TRIGGER users_before_insert BEFORE INSERT ON `users`
FOR EACH ROW BEGIN
SET NEW.email_hash = UNHEX(SHA1(new.email)); -- You can remove UNHEX if you want human-readable value. You'll need binary(40) to hold it then
END;
DELIMITER ;
在您的应用程序中,您只需提供名字,姓氏和电子邮件的值。 MySQL将处理重复项,它将以23000
状态向您发出信号。我不知道如何使用asp.net
因此您必须以某种方式调整其错误处理。
你可以在你的asp.net应用程序中处理哈希,但是如果你让数据库做到这一点感觉更舒服 - 我展示了如何通过触发器来实现它。
如果要求手机号码是唯一的或任何其他字段,则同样的规则适用于手机号码。当然,散列数字可能会产生比实际数字更长的散列值,在这种情况下,您可能只是直接制作移动号码unique
。
我希望这对你做什么的决定有所帮助。
答案 1 :(得分:0)
评论太多了......
如果您已经有INDEX(email)
,那么只需将其转为UNIQUE(email)
即可。表(数据+索引)大小不会改变(由ALTER
引起的更多)。
如果email
太大而无法编制索引 - 例如因为它是TEXT
- 那么就无法在UNIQUE
上添加email
索引。在这种情况下,“哈希”解决方案将起作用。是的,它会为磁盘使用量增加兆字节,但这不太可能是一个问题。
如果您目前有id AUTO_INCREMENT
和PRIMARY KEY(id)
,那么您是否真的在其他表中使用id
?如果没有,那么我们可以讨论其他路径,例如email
或hash
PRIMARY KEY
。这个可能甚至会缩小磁盘占用空间。
无论你做什么,都要使用InnoDB。
答案 2 :(得分:-1)
如果您正在进行唯一的密钥查找,那么它确实没有足够的性能差异来担心索引是否已群集。在向表中添加更多内容时,将它聚类可能是有意义的(或不是)。主要的是你有一个独特的约束,很可能这将是主键,所以你将得到它和相应的索引。性能会很好 - 关注其他用途。例如如果您想对域进行分析,则可能需要分解电子邮件地址。这可能更重要。像大多数事情一样,它取决于....