2008-10-05 79 views
3

處理在SQL Server 2005中存儲和索引URL的最佳方式是什麼?SQL Server 2005中的索引URL

我有一個WebPage表,用於存儲有關Web頁面的元數據和內容。我也有許多與WebPage表相關的其他表。他們都使用URL作爲關鍵。

問題是URL的可能非常大,並且將它們用作關鍵字會使索引變大和變慢。我不知道多少,但我已經多次閱讀使用大字段索引是避免。假設URL是nvarchar(400),它們是用作主鍵的巨大字段。

有什麼替代方案?

將URL用作密鑰而不是較小的字段可能會帶來多少痛苦。

我已經查看了具有標識列的WebPage表,然後將其用作WebPage的主鍵。這樣可以使所有相關索引變得更小,更高效,但是導致導入數據有點痛苦。關聯表的每個導入都必須先在表中插入數據之前查找url的標識。

我也玩過在URL上使用散列,創建一個較小的索引,但我還不確定它是否是最好的處理方式。它不會是一個獨特的索引,並且會受到少量碰撞的影響。所以我不確定在這種情況下使用的外鍵......

關於存儲在數據庫中的網頁會有數百萬條記錄,並且會有很多批量更新。另外還會有相當多的閱讀和彙總數據的活動。

有什麼想法?

回答

4

我會使用正常的標識列作爲主鍵。你說:

這使所有相關的索引更小,更高效 但它使導入數據有點痛苦。 關聯表的每個導入都必須先在表中插入數據之前查找url的ID爲 。

是的,但是痛苦可能是值得的,你在過程中學到的技術對於未來的項目是非常寶貴的。

在SQL Server 2005中,您可以創建一個用戶定義的函數GetUrlId,看起來像

CREATE FUNCTION GetUrlId (@Url nvarchar(400)) 
RETURNS int 
AS BEGIN 
    DECLARE @UrlId int 
    SELECT @UrlId = Id FROM Url WHERE Url = @Url 
    RETURN @UrlId 
END 

這會在你的URL表格中已經返回ID爲URL和NULL對於尚未錄得任何網址。然後,您可以調用這個函數內聯import語句 - 類似

INSERT INTO 
    UrlHistory(UrlId, Visited, RemoteIp) 
VALUES 
    (dbo.GetUrlId('http://www.stackoverflow.com/'), @Visited, @RemoteIp) 

,這大概比一個合適的聯合聲明慢,但對於一次性或偶爾進口程序它可能使事情變得更容易。

1

我會堅持哈希解決方案。這會產生一個碰撞機率很低的獨特鑰匙。

另一種方法是創建GUID並將其用作關鍵字。

+0

如果使用散列解決方案,相關表對外鍵使用什麼?你不能使用散列,因爲你會碰到? – 2008-10-05 16:03:38

+0

我認爲GUID解決方案與識別列相同。在相關表中使用GUID之前,每個導入程序都必須打開WebPage表才能將URL從URL轉換爲GUID。 – 2008-10-05 16:05:10

2

根據您所關注的位將URL分成若干列,並使用RFC作爲指導。反轉主機和域信息,以便索引可以像域一樣分組(谷歌這樣做)。

stackoverflow.com  -> com.stackoverflow 
blog.stackoverflow.com -> com.stackoverflow.blog 

谷歌有一篇文章,概述了他們做了什麼,但我現在找不到。

http://en.wikipedia.org/wiki/Uniform_Resource_Locator

0

我完全同意迪倫。在WebPage表中使用IDENTITY列或GUID列作爲代理鍵。這是一個乾淨的解決方案。導入時的id查找並不是那麼痛苦,我認爲。

將big varchar列用作鍵列會浪費很多空間並影響插入和查詢性能。

0

不是一個解決方案。更多另一個角度。

存儲一個頁面的全部唯一URI可能會破壞URI構造的一部分。每個正斜槓應該指的是域內唯一的語義空間(無論該空間是實際的還是邏輯的)。除非您打算存儲的URI是沿着www.somedomain.com/p.aspx?id=123456789的行,否則真的可能會更好地將單個URI metatable分解成代表您網站中代表的子域的表。

例如,如果您要在「評論」URI相同的表中保留一些「新聞」部分的URI,那麼您就錯過了一個技巧,讓其中的內容包含元信息的「部分」表關於該部分,並且其自己的ID充當其中所有這些URI的父代。

1

「假設一個URL類型爲nvarchar(400)」

我不認爲URL的需要是nvarchar的,普通的VARCHAR應該足夠了。