SQL Server 2005中的索引URL

时间:2008-10-05 15:54:07

标签: sql-server performance

在SQL Server 2005中处理存储和索引URL的最佳方法是什么?

我有一个WebPage表,用于存储有关Web页面的元数据和内容。我还有许多与WebPage表相关的其他表。他们都使用URL作为密钥。

问题是URL可能非常大,并且将它们用作键会使索引变得更大和更慢。我不知道多少,但我已经读了很多次使用大字段进行索引是要避免的。假设URL是nvarchar(400),则它们是用作主键的巨大字段。

有哪些替代方案?

使用网址作为密钥而不是较小的字段可能会产生多大的痛苦。

我查看了具有标识列的WebPage表,然后将其用作WebPage的主键。这使得所有相关索引更小,更高效,但这使得导入数据有点痛苦。在表中插入数据之前,关联表的每次导入都必须首先查找url的id。

我还在网址上使用哈希来创建一个较小的索引,但我仍然不确定它是否是最好的做事方式。它不会是一个独特的索引,并且会受到少量冲突的影响。所以我不确定在这种情况下会使用什么外键...

数据库中将存储数百万条关于网页的记录,并且会有大量的批量更新。此外,还会有大量的活动阅读和汇总数据。

有什么想法吗?

6 个答案:

答案 0 :(得分: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表中已有的URL的ID,并且对于尚未记录的任何URL,返回NULL。然后,您可以调用此函数内联您的import语句 - 类似于

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

这可能比正确的连接语句慢,但对于一次性或偶尔的导入例程,它可能会使事情变得更容易。

答案 1 :(得分:2)

根据您关注的位将URL拆分为列,并使用RFC作为指南。反转主机和域信息,以便索引可以像域一样分组(Google会这样做)。

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

谷歌有一篇论文概述了他们的所作所为,但我现在找不到。

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

答案 2 :(得分:1)

我会坚持使用哈希解决方案。这会生成一个碰撞机率很低的唯一键。

另一种方法是创建GUID并将其用作密钥。

答案 3 :(得分:1)

“假设网址为nvarchar(400)”

我认为URL不需要是nvarchar,普通的varchar就足够了。

答案 4 :(得分:0)

我完全同意迪伦的观点。使用IDENTITY列或GUID列作为WebPage表中的代理键。这是一个干净的解决方案。导入时查找id并不是我想的那么痛苦。

使用大型varchar列作为键列会浪费很多空间并影响插入和查询性能。

答案 5 :(得分:0)

与其说是解决方案。更多另一种观点。

存储页面的总唯一URI可能会破坏URI构造的一部分。每个正斜杠都应该引用域内的唯一语义空间(无论该空间是实际的还是逻辑的)。除非您打算存储的URI与www.somedomain.com/p.aspx?id=123456789一致,否则将单个URI metatable分解为表示您在站点中表示的子域的表可能更好

例如,如果您要在与“评论”URI相同的表中保存多个“新闻”部分URI,那么您就会错过一个“Sections”表,其内容包含有关元信息的元素信息该部分及其自己的ID充当其中所有URI的父级。