2017-04-25 40 views
0

我有一個包含數百萬電子郵件ID記錄的註冊表。電子郵件ID是獨一無二的。爲了進行身份驗證,使用asp.net將它們編入索引並獲取它們的最佳方法是什麼?我的意思是我應該將電子郵件ID列定義爲聚集的唯一索引而不是UNIQUE?在MYSQL中索引電子郵件地址的最佳方法是什麼

+1

您使用的是MySQL還是MSSQL? MySQL沒有聚集的唯一索引。你可以對電子郵件進行散列處理(比如用'sha1'),並將其保存爲二進制文件,每次將腳印減少到20個字節,並且該列旁邊有明文電子郵件地址值。使哈希獨一無二,現在您擁有固定長度的唯一標識符。 – Mjh

+0

對電子郵件地址進行散列處理,將它們轉換爲二進制文件,然後將它們存儲在電子郵件列旁邊的數據庫中是什麼意思。它會增加數據庫的大小。它不會解決我的問題,反而會增加它。我想通過實施索引來縮短查詢時間。 – Deep

+0

電子郵件地址具有可變長度。如果您散列可變長度值,您的索引將會有所不同,並且當您嘗試索引過大的值時,索引還有其他問題。爲了減少這個問題,你不需要索引電子郵件的實際字符串值,但是它的哈希值是因爲哈希值是固定長度的。它確實解決了你的問題,並且你沒有任何可以來回轉換的東西。 – Mjh

回答

1

當你有一個可變長度的文本輸入,如e-mail或地址,但你希望他們是唯一的,則標準方法是指數的哈希那個價值。

原因:散列是固定長度的,並且您避免了超出索引長度的文本數據的問題。

根據您的意見,你有看起來像這樣的表(我故意省略密碼和手機號碼):

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

我希望這可以幫助你決定做什麼。

0

如果你正在做一個獨特的密鑰查找,它確實沒有足夠的性能差異來擔心索引是否被聚集。在向表中添加更多內容時,對其進行羣集可能是有意義的(或不是)。主要的是你有一個唯一的約束,很可能這將是主鍵,所以你會得到這個和相應的索引。性能會很好 - 關注其他用途。例如如果您想對域進行分析,則可能需要分解電子郵件地址。這可能更重要。最喜歡的事情,這取決於....

+0

感謝您的幫助。但我想澄清一件事。我有一個單獨的ID列,我已經聲明爲主鍵,但是我正在考慮將emailID聲明爲主鍵和Auto inc。因爲我已經宣佈它是唯一的。如果我有數百萬條記錄,它肯定會減少我的數據庫的大小。如果我錯了,請糾正我。謝謝.. :) – Deep

+0

@Deep - 什麼是'emailID'?電子郵件地址的價值?你打算如何使自動遞增?只需保留主鍵,將電子郵件的散列添加爲「唯一」,這樣您就不會重複,並且所有問題都消失了。您可以快速查詢,您可以快速檢索,您可以只插入唯一的電子郵件 - 不要過度使用它,因爲您會發現哪裏沒有問題。數以百萬計的記錄都不算什麼,所以不要過於擔心數百萬條記錄。 – Mjh

+0

您不需要此ID。即使你決定包含它,你也需要在電子郵件中添加一個唯一的非空限制,這實際上是PK。如果你需要在電子郵件上使用外鍵,那麼可能會保留該ID,但這不在你在這裏描述的範圍內。不知道爲什麼Mjh對電子郵件進行哈希處理如此堅持 - 這不是必要的,會使所有事情複雜化,併爲錯誤開放。我不會那樣做。 – LoztInSpace

0

事情太多了評論...

如果你已經有INDEX(email),然後簡單地把它變成UNIQUE(email)。表格(數據+索引)的大小不會改變(比ALTER多一點)。

如果email太大而無法索引 - 比如因爲它是TEXT - 那麼無法在email上添加UNIQUE索引。在這種情況下,「散列」解決方案將起作用。是的,它會爲磁盤使用增加兆字節,但這不太可能成爲問題。

如果您目前有id AUTO_INCREMENTPRIMARY KEY(id),那麼您是否真的在其他表中使用id?如果沒有,那麼我們可以討論其他路徑,例如使emailhashPRIMARY KEY。這可能甚至縮小磁盤的足跡。

不管你做什麼,都使用InnoDB。

+0

如果不存儲電子郵件ID的散列,而只是將emai_id聲明爲主鍵而不爲空,它會爲我做這件事嗎?但主鍵本身是一個獨特的聚集索引,這對我來說可能是一個問題。 – Deep

+0

使用'PRIMARY KEY(email)','INSERT''再次發送同一封電子郵件將失敗(重複密鑰)。另見'INSERT ... ON DUPLICATE KEY UPDATE ...'。 –

相關問題