为什么以下查询复制表数据?

时间:2010-12-16 15:30:30

标签: mysql database performance group-by covering-index

SELECT COUNT(*) AS cnt
FROM products
WHERE ExternalProductId IS NOT NULL
GROUP BY SourceId, ExternalProductId
HAVING cnt > 1

(ExternalProductId,SourceId,AnotherField)上有一个索引。解释显示使用了索引。这打印在解释的“额外”栏中:

Using where; Using index; Using temporary; Using filesort

当我运行查询时,我通过SHOW PROCESSLIST看到:

Copying to tmp table on disk

我可以调整此查询以在索引上就位吗?我也不介意我得到的结果是否稍微不准确,因为同时处理此表的其他进程 - 我可以更改隔离级别以提高查询的性能吗?

2 个答案:

答案 0 :(得分:3)

如果您反转GROUP BY中的列以与复合索引的前两个字段的顺序相对应,它将更有效地使用您的复合索引。

SELECT COUNT(*) AS cnt
FROM products
WHERE ExternalProductId IS NOT NULL
GROUP BY ExternalProductId, SourceId
HAVING cnt > 1

您的查询执行简单应变为'Using where; Using index',并删除由其他GROUP BY引起的临时表和文件排序。

你仍会得到相同的结果,但它的顺序会略有不同。

答案 1 :(得分:0)

有几件事要尝试:

  1. MySQL会自动按组排序。如果您不关心排序顺序,请添加“ORDER BY NULL”子句。这将取出filesort和可能的临时表。

  2. 删除计数(*)并使用索引中的列名而不是通配符。

  3. 另外。你的指数是多少?你能告诉我们全表创建语句吗?