我有一个存储要抓取的 URI 列表的表。这个'crawl_index'表模式是:
CREATE TABLE `crawl_index` (
`id` INTEGER(10) NOT NULL AUTO_INCREMENT,
`uri` TEXT NOT NULL,
`domain` VARCHAR(255) NOT NULL,
`last_crawled_date` INTEGER(10) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
INDEX `crawler_INDEX_1` (`domain`),
INDEX `crawler_INDEX_2` (`last_crawled_date`)
) ENGINE=InnoDB;
有关此表的一些详细信息:
- 它包含大约 1M 行。
- 近 60% 的行将“last_crawled_date”设置为 0(从爬取的页面中提取 URI 比实际爬取页面要快)。
- “id”字段从未使用过。我只将它添加到架构中以获得显式的 primary_key,因为我无法在“uri”字段上创建主键,因为它是未绑定的文本。
我想要做的是选择具有以下约束的 N 行:
- 该 URI 在过去 2 天内不应被抓取
- 我不希望所有返回的 URI 都来自同一个域,以避免同时在同一个域上执行太多请求。
目前,我尝试了这个查询:
select * from crawl_index where last_crawled_date <= 1373273029 group by domain limit 3;
它给了我这种结果:
+--------+------------------------+--------------+-------------------+
| id | uri | domain | last_crawled_date |
+--------+------------------------+--------------+-------------------+
| 60239 | http://example1.com/1 | example1.com | 0 |
| 239 | http://example2.com/1 | example2.com | 0 |
| 120239 | http://example3.com/1 | example3.com | 0 |
+--------+------------------------+--------------+-------------------+
3 rows in set (1,23 sec)
它可以工作,但与没有“group by”语句的相同查询相比,它相当慢。当我运行explain
该查询时,我得到了这个:
+----+-------------+-------------+-------+-----------------+-----------------+---------+------+-------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+-------+-----------------+-----------------+---------+------+------+------------------------+
| 1 | SIMPLE | crawl_index | range | crawler_INDEX_1 | crawler_INDEX_2 | 4 | NULL | 71588 | Using index condition |
| | | | | crawler_INDEX_2 | | | | | Using temporary |
| | | | | | | | | | Using filesort |
+----+-------------+-------------+-------+-----------------+-----------------+---------+------+-------+-----------------------+
我已经 :
- 在 last_crawled_date 和 domain 字段上创建索引
- 使用整数来存储我的 last_crawled_date 以避免日期时间比较
- 在我的 PHP 代码中预先计算 max_date 以避免让 mysql 为我做这件事。
知道我可以改进这个查询吗?