如何在MySQL中存储URL

mer*_*inn 11 mysql

我需要在数据库中存储数百万个URL.每个URL都应该是唯一的,因此我将使用ON DUPLICATE KEY UPDATE并计算重复的URL.

但是,我无法在URL字段上创建索引,因为我的varchar字段是400个字符.MySQL抱怨并说; "#1071 - 指定密钥太长;最大密钥长度为767字节".(Varchar 400将占用1200字节)

如果您需要在一台服务器中每天处理至少500000个URL,那么最好的方法是什么?

我们已经在考虑将MongoDB用于相同的应用程序,因此我们可以简单地查询MongoDB并找到重复的URL,并更新该行.但是,我并不赞成使用MongoDB来解决这个问题,我想在这个阶段只使用MySQL,因为我希望在开始时尽可能精简并更快地完成项目的这一部分.(我们还没有玩过MongoDB,也不想在这个阶段花时间)

使用更少的资源和时间是否还有其他可能性.我想要获取URL的MD5哈希并存储它.而且我可以将该字段改为UNIQUE.我知道,会有冲突,但如果这是唯一的问题,那么在1亿个网址中可以有5-10-20个重复项.

你有什么建议吗?我也不想花10秒钟只插入一个URL,因为它每天会处理500k个URL.

你会建议什么?

编辑:根据请求,这是表定义.(我现在不使用MD5,它用于测试)

mysql> DESC url;
+-------------+-----------------------+------+-----+-------------------+-----------------------------+
| Field       | Type                  | Null | Key | Default           | Extra                       |
+-------------+-----------------------+------+-----+-------------------+-----------------------------+
| url_id      | int(11) unsigned      | NO   | PRI | NULL              | auto_increment              |
| url_text    | varchar(400)          | NO   |     |                   |                             |
| md5         | varchar(32)           | NO   | UNI |                   |                             |
| insert_date | timestamp             | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| count       | mediumint(9) unsigned | NO   |     | 0                 |                             |
+-------------+-----------------------+------+-----+-------------------+-----------------------------+
5 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

Pat*_*Pat 10

根据DNS规范,域名的最大长度为:

DNS本身仅对
可用于标识资源记录的特定标签设置一个限制.该限制
涉及标签的长度和全名.
任何一个标签的长度限制在1到63个八位字节之间.完整域名
限制为255个八位字节(包括分隔符).

255*3 = 765 <767(勉强:-))

但请注意,每个组件的长度只能为63个字符.

所以我建议将网址砍成组件位.

使用http://foo.example.com/a/really/long/path?with=lots&of=querymeters=that&goes=on&forever&and =ever

这可能就足够了:

  • protocol flag ["http" - > 0](将"http"存储为0,将"https"存储为1,等等)
  • subdomain ["foo"](255 - 63 = 192个字符:我可以减去2个,因为min tld是2个字符)
  • domain ["example"],(63个字符)
  • tld ["com"](处理"info"tld的4个字符)
  • path ["a/really/long/path"](只要你想要 - 存储在一个单独的表中)
  • queryparameters ["with = lots&of = query¶meters = that&goes = on&forever&and = ever"](存储在单独的键/值表中)
  • 如果实际需要,很少使用的portnumber/authentication东西可以在一个单独的键控表中.

这给你一些很好的优势:

  • 索引仅在您需要搜索的URL的部分上(较小的索引!)
  • 查询可以限于各种url部分(例如,在facebook域中查找每个url)
  • 任何具有太长子域/域的URL都是假的
  • 容易丢弃查询参数.
  • 容易做不区分大小写的域名/ tld搜索
  • 丢弃语法糖(协议后为"://",子域/域之间为".",tld和路径之间为"/",查询前为"?",查询中为"&""=")
  • 避免主要的稀疏表问题.大多数网址不具有查询参数,也不具有长路径.如果这些字段位于单独的表中,那么您的主表将不会占用大小.在进行查询时,更多记录将适合内存,因此查询性能更快.
  • (这里有更多优势).