我有一个表,其中存储要爬网的 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;
有关此表的一些详细信息:
- 它包含大约 100 万行。
- 近 60% 的行的“last_crawled_date”设置为 0(从已抓取的页面中提取 URI 比实际抓取页面更快)。
- “id”字段从未被使用过。我只是将其添加到架构中以具有显式的 Primary_key,因为我无法在“uri”字段上创建主键,因为它是未绑定(bind)的文本。
我想要做的是选择具有以下约束的 N 行:
- 过去 2 天内不应抓取该 URI
- 我不希望所有返回的 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 和域字段上创建索引
- 使用整数存储我的last_crawled_date以避免日期时间比较
- 在我的 PHP 代码中预先计算 max_date,以避免要求 mysql 为我执行此操作。
知道我可以改进这个查询吗?
最佳答案
尝试在(last_crawled_date,domain)上创建复合索引并查看解释计划。它应该减少执行时间。也删除其他索引并进行测试。
关于MySQL - "Group by"的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17588499/