2012-08-16 76 views
1

我試圖在外觀和行爲中創建類似於YouTube的/v=xxx的網址。簡而言之,用戶將上傳文件並能夠通過該URL訪問它們。該URL代碼需要是某種形式的數據庫主鍵,以便頁面可以收集所需的數據。我是數據庫新手,這比數據庫問題更重要。主鍵的唯一網址

在我的數據庫中,我有一個自動遞增主鍵,可以訪問文件數據。我想用這個數字來創建文件的URL。我開始研究不同的哈希函數,但我擔心碰撞。我不希望兩個不同文件的URL相同。

我也考慮使用uniqid()作爲我的主鍵CHAR(13),並直接使用。但是,我擔心效率問題。同樣環顧四周,我似乎無法找到很多關於它的內容,所以這可能是一個奇怪的想法。更不用說,當生成可能效率低下的ID時,我需要測試碰撞。自動增量更容易。

有沒有什麼好的解決方案呢?我的想法是否有用?如何從自動遞增的主鍵生成唯一的URL並避免衝突?

我傾向於第二個想法,效率不高,但是當需要將事物添加到數據庫(測試碰撞)時會導致最大的性能缺陷,而最終用戶只需要發生一次。另一個性能缺點可能在於實際查看字符而不是整數。但我主要擔心這是不好的做法。

編輯:

簡單的解決辦法是隻需直接使用自動遞增值。叫我挑剔,但看起來很醜陋。

+0

你預計你會有多少記錄? – sberry 2012-08-16 16:50:11

+1

爲什麼你認爲使用自動遞增的值是醜陋的? – Briguy37 2012-08-16 16:52:52

+0

@sberry這真的取決於,從一開始就不是很多。但我認爲值得注意的是,2個月後文件將被刪除。因此,一次只能有幾千人樂觀。 – SpaceFace 2012-08-16 16:54:18

回答

1

非產生碰撞的短哈希的確會讓人頭疼。所以,相反#1的蛞蝓格式是非常有前途的並保證會產生非重複的網址。

例如,這個非常相同的問題有

https://stackoverflow.com/questions/11991785/unique-url-from-primary-key

在這裏,它具有獨特的主鍵,也是一個標題,使其更加SE友好。


然而,正如評論,他們以前提出的問題很少,可能會清楚,爲什麼?你正在嘗試更好地被排除在外。

  1. How to generate a unique hash for a URL?
  2. Create Tinyurl style hash

創建短哈希增加了機會碰撞了很多,所以更好的用戶base64sha512函數來創建一個安全的哈希值。

+0

你是對的,但是這不是他所提出的要求。他也可以只使用主鍵(號),但他需要用字符短網址。 – 2012-08-16 17:00:26

+1

我其實很喜歡這個想法。 – SpaceFace 2012-08-16 17:05:22

0

你可以簡單地做的時間哈希,事後檢查的散列(或你的數據庫 散列的一部分。如果你在你的數據庫設置該領域的指數(並確保哈希足夠長爲不使很多衝突的),也不會在所有時間上的問題。

<?php 

$hashChecked = false; 

while($hashChecked === false){ 
    $hash = substr(sha1(time().mt_rand(9999,99999999)), 0, 8); //varchar 8 (make sure that is enough with a very big margin) 
    $q = mysql_query("SELECT `hash` FROM `tableName` WHERE `hash` = '".$hash."'"); 
    $hashChecked = mysql_num_rows() > 0 ? false : true; 
} 

mysql_query("INSERT INTO `tableName` SET `hash` = '".$hash."'"); 
+0

你的while循環永遠不會觸發它,你會得到一個碰撞,併爲每個插入做一個選擇是不需要的開銷。 – sberry 2012-08-16 16:53:17

+0

你是對的,我改變了代碼。唯一避免「開銷」的方法是使用自動增量字段。 – 2012-08-16 16:55:38

0

如果您願意使用隨機數來生成短網址,這是相當直接的。例如,你可以這樣做:

SELECT BASE64_ENCODE(CAST(RAND()*1000000 AS UNSIGNED INTEGER)) AS tag 

這是能夠給你一百萬個不同的標籤。要獲得更多可能的標籤,請增加RAND()數字的乘積值。這些標籤值很難預測。

爲了確保您不會得到重複項,您需要重新標記標記值。這很容易做到,但需要程序中的邏輯。將標記值插入到將其用作主鍵的表中。如果插入失敗,請重試,重新調用RAND()。

如果您接近最大數量的標籤,您將開始出現大量插入失敗(標籤碰撞)。

BASE64_ENCODE來自您需要安裝的存儲功能。你可以在這裏找到它:

http://wi-fizzle.com/downloads/base64.sql

如果你使用MySQL 5.6或更高版本可以使用內置的TO_BASE64功能。

0

我想要做類似的東西(但文章,沒有上傳文件),並與東西有點不同想出了:

  • 取質數[Y](多)比最大數量較大[n]的文件將永遠存在(例如,25000將足夠大的文件總數,並且1000099是比25001更大的素數)
  • 對於當前文檔id [x]:(x * y )模數(n + 1)
  • 這將產生一個從1到n的數字,這是從不復制的

儘管url可能看起來像一個傳統的主鍵,但它有一個小優點,即每個後續文檔都會有一個與前一個文檔完全無關的id;有些人還認爲,不包括主鍵也有很小的安全優勢...