MySQL-与“MySQL”有关的性能问题;分组方式;

MySQL-与“MySQL”有关的性能问题;分组方式;,mysql,sql-order-by,web-crawler,filesort,Mysql,Sql Order By,Web Crawler,Filesort,我有一个存储要爬网的URI列表的表。此“爬网索引”表架构为: 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 N

我有一个存储要爬网的URI列表的表。此“爬网索引”表架构为:

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”字段从未使用过。我只是将其添加到模式中以具有显式主键,因为我无法在“uri”字段上创建主键,因为它是未绑定的文本
我要做的是选择具有以下约束的N行:

  • URI在过去2天内不应已爬网
  • 我不希望所有返回的URI都来自同一个域,以避免同时在同一个域上执行太多请求
目前,我尝试了以下查询:

select * from crawl_index where last_crawled_date <= 1373273029 group by domain limit 3;
它可以工作,但与没有“GROUPBY”语句的同一查询相比,速度相当慢。当我对该查询运行
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        |
+----+-------------+-------------+-------+-----------------+-----------------+---------+------+-------+-----------------------+
我已经:

  • 在上次爬网的日期和域字段上创建索引
  • 使用整数存储上次爬网的日期,以避免日期时间比较
  • 在我的PHP代码中预先计算max_date,以避免要求mysql为我这样做
你知道我可以改进这个问题吗

使用文件排序

这就是问题所在。您可以增加所用DB引擎的内存限制


另一种解决方案是:您可以在域列上使用
ENUM
,而不是
VARCHAR(255)

尝试在(上次爬网日期,域)上创建一个复合索引,并查看解释计划。它应该减少执行时间。同时删除其他索引并进行测试。

使用
ENUM
似乎是不可能的,因为每次我们要添加一个新的域进行爬网时都会更新架构。增加内存限制是个好主意。我将测试它,并告诉您它是否提高了性能。但现在,我正试图理解为什么解释突然告诉我,它不再使用“文件排序”、“临时”和“索引”,而是使用“where”。。。我所做的唯一更改是在表中添加几十万个URI来模拟生产约束。响应时间基本保持不变:在1.5到2秒之间。奇怪。。。
+----+-------------+-------------+-------+-----------------+-----------------+---------+------+-------+-----------------------+
| 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        |
+----+-------------+-------------+-------+-----------------+-----------------+---------+------+-------+-----------------------+