在MYSql中索引电子邮件地址的最佳方法是什么

在MYSql中索引电子邮件地址的最佳方法是什么,mysql,indexing,Mysql,Indexing,我有一个注册表,里面有数百万的电子邮件id记录。电子邮件ID是唯一的。为了进行身份验证,使用asp.net为它们编制索引并取回它们的最佳方法是什么?我的意思是,我应该将电子邮件id列定义为聚集的唯一索引而不是唯一索引吗?如果您正在执行唯一键查找,那么如果索引是聚集的或不是聚集的,那么性能差异就不会太大。在向表中添加更多内容时对其进行集群可能有意义(或者没有意义)。最重要的是你有一个唯一的约束,很可能这是主键,所以你会得到它和相应的索引。性能将是良好的-关注自己的其他用途。e、 如果你想对域名进行

我有一个注册表,里面有数百万的电子邮件id记录。电子邮件ID是唯一的。为了进行身份验证,使用asp.net为它们编制索引并取回它们的最佳方法是什么?我的意思是,我应该将电子邮件id列定义为聚集的唯一索引而不是唯一索引吗?

如果您正在执行唯一键查找,那么如果索引是聚集的或不是聚集的,那么性能差异就不会太大。在向表中添加更多内容时对其进行集群可能有意义(或者没有意义)。最重要的是你有一个唯一的约束,很可能这是主键,所以你会得到它和相应的索引。性能将是良好的-关注自己的其他用途。e、 如果你想对域名进行分析,你可能需要分解电子邮件地址。这可能更重要。与大多数事情一样,这取决于……

当您有可变长度的文本输入,如电子邮件或地址,但您希望它们是唯一的,那么标准方法是为该值的哈希值编制索引

原因:哈希是固定长度的,您可以避免文本数据超过索引长度的问题

根据您的评论,您的表格如下所示(我故意省略了密码和手机号码):

我将修改该表并添加一个包含电子邮件哈希的字段。我会通过触发器来维护它,这样您就可以专注于获取有效数据,而不用担心创建散列。为此,该字段将是
binary(20)
,因为它将包含原始散列,需要20个字节。因为我们希望通过触发器来维护它,所以我们需要使该字段为空且唯一。注意:您可以将其设置为二进制(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应用程序中处理哈希,但是如果您觉得让数据库这样做更舒服的话-我演示了如何通过触发器实现它

同样的规则也适用于手机号码,如果您要求它是唯一的或任何其他字段。当然,对数字进行散列可能会产生比实际数字更长的散列值,在这种情况下,您可以直接使移动电话号码
唯一


我希望这能对你的决定有所帮助。

有太多的事情需要评论

如果您已经有
索引(电子邮件)
,只需将其转换为
唯一(电子邮件)
。表(数据+索引)的大小不会发生变化(由于
的更改,变化幅度不会太大)

如果
电子邮件
太大而无法索引,例如因为它是
文本
,则无法在
电子邮件
上添加
唯一的
索引。在这种情况下,“散列”解决方案将起作用。是的,它会增加磁盘使用量的兆字节,但这不太可能是一个问题

如果您当前有
id自动递增
主键(id)
,那么您是否在其他表中实际使用
id
?如果没有,那么我们可以讨论其他途径,例如制作
电子邮件
散列
主键
。这甚至可能会缩小磁盘占用空间


无论您做什么,都要使用InnoDB。

您使用的是MySQL还是MSSQL?MySQL没有聚集的唯一索引。您可以对电子邮件进行散列(例如,使用
sha1
)并将其保存为二进制,这样每次占用的空间就减少到20字节,并且在该列旁边有电子邮件地址的纯文本值。使散列唯一,现在您有了固定长度的唯一标识符。对电子邮件地址进行散列,将其转换为二进制,然后将其存储在电子邮件列旁边的数据库中有什么意义。它将增加数据库的大小。它不会解决我的问题,反而会增加我的问题。我想通过实现索引来减少查询时间。电子邮件地址具有可变长度。如果散列一个可变长度的值,则索引会发生变化,并且当您尝试索引一个太大的值时,索引还有其他问题。为了减少这个问题,您不索引电子邮件的实际字符串值,而是索引其哈希值,因为哈希值是固定长度的。它确实解决了您的问题,而且您没有任何东西需要来回转换。@Mjh-MySQL(使用InnoDB)
主键
是唯一的,并且是集群的。@RickJames同样,考虑到这个问题的上下文和OP正在做什么-是的,他可以简单地跳过自动增量,使用电子邮件作为主键。这是否有用,速度是否更快,是否符合他的要求——他必须进行测试。有一件事是肯定的——有一个好的号码给你提供记录识别确实有帮助。这是我个人的意见。您的解决方案可能有效,但没有迹象表明无效。我会看看杰里米·科尔的博客,谢谢你的指点!谢谢你的帮助。但我想澄清一件事。我有一个单独的ID列,我已经声明为主键,但是我想声明emailID为主键,Auto inc.因为我已经声明它是唯一的。如果我有数百万条记录,它肯定会缩小我数据库的大小。如果我错了,请纠正我。谢谢……)@深度-什么是
emailID
?电子邮件地址的价值?您计划如何使其自动递增?只需保持主键不变,将电子邮件的哈希值添加为
unique
,这样您就不会得到重复项,所有问题都会消失。你可以快速查询,你可以快速检索,哟
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 ;