我有两个表,它们代表 url 列表及其相关的单词索引。以下是供参考的表定义。
desc urllist;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| url | text | NO | | NULL | |
+-------+---------------------+------+-----+---------+----------------+
和
desc wordlocation;
+----------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------------+------+-----+---------+-------+
| urlid | bigint(20) unsigned | NO | | NULL | |
| wordid | bigint(20) unsigned | NO | | NULL | |
| location | int(10) unsigned | NO | | NULL | |
+----------+---------------------+------+-----+---------+-------+
该软件应用程序是一个网络蜘蛛。它爬取一个 url 列表,提取这些 url,并将它们插入到urllist
表中。然后,索引器检查哪些 url 还没有被索引,然后继续索引这些 url。
这是我用来在左表 ( urllist
) 中查找尚未在右表 ( wordlocation
) 中编制索引的项目的查询。此查询与mysql.com 网站上的建议一致:
select * from urllist ul
left join wordlocation wl on ul.id = wl.urlid
where wl.urlid IS NULL;
在撰写本文时,我的测试数据库只有 600 个索引 url,而 wordlocation 表有 130 万行。但是,我的 CPU 是 100%,我等待查询是否完成的最长时间是半小时(顺便说一句,它从来没有这样做过)。
为了彻底,这里是查询的解释:
explain select * from urllist ul left join wordlocation wl on ul.id = wl.urlid where wl.urlid IS NULL;
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------------------+
| 1 | SIMPLE | ul | ALL | NULL | NULL | NULL | NULL | 50364 | |
| 1 | SIMPLE | wl | ALL | NULL | NULL | NULL | NULL | 1351371 | Using where; Not exists |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------------------+
我需要这个查询在几秒钟内完成,而不是几分钟。另外,我担心可扩展性。我有 40,000 个唯一的 url 等待添加到索引中,那么如何在我的表和查询设计中考虑到这一点?400,000 个网址?
关于我对当前表结构的决定的几点说明。
我无意停留在 400,000 个 url,但也许 bigint(20) 有点过分热心?
网址作为文本是出于更实际的原因。我索引了很多亚洲和其他外语域,这些域在数据库中不显示为对应的汉字或其他字符,并且经常占用超过 255 个字符。
我正在使用 MySQL。我绝对愿意接受有关更好的表和查询设计的建议。如果我能提供更多信息,请告诉我。