我正在开发一个爱好项目,该项目包含一个抓取网页以获取信息的模块。数据库管理不是我最擅长的方面,我现在已经到了需要帮助的地步。我已经设置了 10 个爬虫,它们最快在发布后 3 分钟从表中同时爬取页面,并且不迟于发布后 60 天(这些时间间隔与爬取系统的工作方式有关)。我有的是三张桌子:
一个页面内容表,其中包含来自已爬取页面的所有信息以及这些页面的一些元数据(例如从外部源更新的发布日期)
- 表名:pages
- 列:id (PK)、url、publishingDate、名称、描述、类别...
- 大小:约 500K 行
需要抓取的页面表。此表中的行由外部系统添加,但当爬虫完成对该表中页面的爬取时将其删除。
- 表名:needsCrawling
- 列:pageId(页面的 FK)
- 大小:最多50K
一个爬虫任务表,其中包含 certin 爬虫应该爬取的一组页面:
- 表名:crawlerTaskList
- 列:id(PK),crawlerId(称为爬虫的表的FK),pageId(页面的FK)
- 大小:最多 1K 行(10 个爬虫,每个爬虫的任务列表中永远不会超过 100 页)
这背后的想法是表1(页面)用于获取发布日期,然后用于存储获取的爬取结果。表号 2 用于“标记”哪些页面应该被抓取,然后在它们被抓取后移除“标记”(仍然必须检查发布日期,因为一个页面可能需要抓取,而不是之前,已满足发布日期标准)。表3(crawlerTaskList)主要用于防止爬虫爬取相同的页面。
我最初用来为爬虫获取 url 的查询如下所示:
SELECT id, url
FROM pages
WHERE publishingDate < NOW() - INTERVAL 3 minute
AND DATE_SUB(CURDATE(), INTERVAL 60 DAY) < publishingDate
AND id NOT IN (SELECT pageId FROM crawlerTaskList)
AND id IN (SELECT pageId FROM needsCrawling)
ORDER BY publishingDate
在页表达到大约 300K 之前,它一直运行良好。现在我已经达到了查询大约需要 40 秒并且开始不可持续的地步。我试图重新编写查询(例如,使用 JOINs 而不是 id IN/id NOT IN)但没有任何改进,所以我迫切需要建议。也许我必须添加一个索引或其他我不知道的花哨的东西。感谢任何花时间阅读所有这些内容的人,并对这篇长篇文章感到抱歉!