MySQL - "Group by"的性能问题

标签 mysql sql-order-by web-crawler filesort

我有一个表,其中存储要爬网的 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/

相关文章:

php - 我可以在 PHP 中混合使用 MySQL API 吗?

php - 记录未从 android 插入到 mysql 数据库表

MySQL 按 2 个表的 2 列对表进行排序

MYSQL高级排序

java - Url 未在网页中返回正确的 html(对于我的 Java 爬虫)

elasticsearch - Storm ui中没有通过拓扑发射或传输元组

mysql - 在 BETWEEN 子句中使用 SQL 子查询获取日期

php - 两个时间戳相加

php - 按 meeting_id DESC 排序

seo - 如果我使用的是 Apache 2,我应该如何处理使用 HTTP/0.9 的蜘蛛/网络爬虫?