在SQL Server 2005中处理存储和索引URL的最佳方法是什么?
我有一个WebPage表,用于存储有关Web页面的元数据和内容。我还有许多与WebPage表相关的其他表。他们都使用URL作为密钥。
问题是URL可能非常大,并且将它们用作键会使索引变得更大和更慢。我不知道多少,但我已经读了很多次使用大字段进行索引是要避免的。假设URL是nvarchar(400),则它们是用作主键的巨大字段。
有哪些替代方案?
使用网址作为密钥而不是较小的字段可能会产生多大的痛苦。
我查看了具有标识列的WebPage表,然后将其用作WebPage的主键。这使得所有相关索引更小,更高效,但这使得导入数据有点痛苦。在表中插入数据之前,关联表的每次导入都必须首先查找url的id。
我还在网址上使用哈希来创建一个较小的索引,但我仍然不确定它是否是最好的做事方式。它不会是一个独特的索引,并且会受到少量冲突的影响。所以我不确定在这种情况下会使用什么外键...
数据库中将存储数百万条关于网页的记录,并且会有大量的批量更新。此外,还会有大量的活动阅读和汇总数据。
有什么想法吗?
答案 0 :(得分:4)
我使用普通标识列作为主键。你说:
这可以使所有关联的索引更小,更高效 但它使导入数据有点痛苦。每次导入都是 关联表必须首先查找url的id是什么 在表格中插入数据之前。
是的,但痛苦可能是值得的,你在这个过程中学到的技术对于未来的项目将是非常宝贵的。
在SQL Server 2005上,您可以创建一个类似于
的用户定义函数GetUrlIdCREATE 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
谷歌有一篇论文概述了他们的所作所为,但我现在找不到。
答案 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的父级。