在Mysql中存储URL的最有效方法是什么?

13

我希望能够在MySql中存储一组大量的URL,并在该列上创建唯一索引。如果我将列声明为utf8,则将限制为varchar(333),这对于一些URL来说不足够。如果我声明该列为latin1,则可以获得完整的1000个字符(我认为不需要那么多)。然而,我必须对URL进行编码并始终使用编码后的URL以保持一致。是否有更好的方法来管理大量的URL?

3个回答

9

有三种好的方法来实现这个:

1)使用TEXT而不是VARCHAR。为了确保唯一性,您还需要创建一个单独的VARCHAR列来存储MD5()或SHA1()哈希并添加UNIQUE或PRIMARY索引。这会导致额外的磁盘查找以检索URL,但根据您的用例,这可能是可以接受的。

2)使用具有二进制排序规则的VARCHAR,并使用COMPRESS()压缩URL。

3)我在打前两个时忘记了第三个。呃...


1
+1,我个人会选择#1(在URL的哈希上放置唯一约束,而不是URL本身)。 - nathan
所以我应该为哈希值创建另一列,而不是将VARCHAR URL列设置为主键? - User
我提出了两个不同的建议。我没有说哪一个更好。你必须选择最适合你使用情况的建议。 - longneck

5

你可能想到的一件事是将URL的主机名和协议部分存储在一个单独的表中,并通过键引用它。这也可以在以后获取特定主机的所有URL时证明有用,同时有助于解决字符串长度问题。

例如:

PROTOCOLS
-----------------------
PROTOCOL_ID   INTEGER
PROTOCOL      VARCHAR(10)    (i.e., http, https, ftp, etc.)

HOSTS
-----------------------
id       BIGINT
hostname varchar(256)   

URL
-----------------------
PROTOCOL      INTEGER  FK to PROTOCOLS
HOSTNAME      BIGINT   FK to HOSTS
QUERY_STRING  VARCHAR(333)

同意。你可能想采用longneck建议的使用文本字段的方法。我更是站在“有没有更好的管理大量URL的方法”的角度来看待这个问题,这也有助于缩短你的URL长度。另外一件事是,根据你如何使用URL,你可能还想将主机名分解为主机和域,并且HOSTS表具有指向DOMAIN表的domain_key。 这可以使查找域内所有URL变得微不足道。 - RC.

0

我知道的最常见的做法是使用带有冲突控制的哈希算法,只需使用某种快速单向编码即可在URL上产生非常低的冲突。

尝试切掉你知道所有URL中都相同的部分(即HTTP://、www等...),如果这些URL都属于你的域名,也将其切掉。

否则,我会重新思考问题,并尝试找到不同的方法来完成你想要完成的任务。我认为拥有一组唯一的URL实际上是在解决其他问题。


2
你可能会对他存储URL的原因做出错误的假设。剪掉www等部分可能是不安全的。 - Matthew Flaschen
可以举个例子吗?去掉"http"和"www"后,你可以轻松地重新生成原始的URL,这不会影响定义的完整性...你能解释一下吗? - Martin Dale Lyness
5
错了,http://www.foo.com 和 http://foo.com 并没有保证是同一个 URL。更别说 https://www.foo.com 和 http://foo.com 了。 - Matthew Flaschen
1
鼠标悬停在链接上。无论如何,重点是该网站免费赋予www子域名特殊意义。 - Matthew Flaschen
2
你千万不要随意截取URL的任何部分,因为即使是微小的差异也可能导致完全不同的页面(例如WWW和非WWW),但我认为哈希的想法很有价值。如果对一个URL进行哈希,那么你只需要执行SELECT WHERE hash ='asdf'就可以抓取到该URL,这可能比执行SELECT WHERE scheme='http',host='google.com',port='80',path='/foo'更快、更高效。但是,这还取决于表规范化程度以及哈希字符串所需的时间,才能决定这是否是最佳方式。 - cjroth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接