5

问题

有谁知道为什么基于 MyISAM 的表没有 GROUP BY 优化?(我使用的是这个版本:5.1.49-3)

测试表

CREATE TABLE `_test2_innodb` (
    `i` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `n` smallint(5) unsigned NOT NULL,
    `t` int(10) unsigned NOT NULL,
    `v` smallint(6) NOT NULL,
    PRIMARY KEY (`i`),
    KEY `i_n` (`n`),
    KEY `i_t` (`t`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

CREATE TABLE `_test2_myisam` (
    `i` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `n` smallint(5) unsigned NOT NULL,
    `t` int(10) unsigned NOT NULL,
    `v` smallint(6) NOT NULL,
    PRIMARY KEY (`i`),
    KEY `i_n` (`n`),
    KEY `i_t` (`t`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

测试查询

SELECT MAX(i) FROM _test2_myisam GROUP BY n;

SELECT MAX(i) FROM _test2_innodb GROUP BY n;

结果

id, select_type, table, type, poss_keys, key, key_len, ref, rows, extra

1, SIMPLE, _test2_myisam , ALL, , , , , 19998, Using temporary; Using filesort

1, SIMPLE, _test2_innodb, index, , i_n, 2, , 20024, Using index

问题是,如果我使用 MyISAM,将完成一次全表扫描,这在大型表上需要几个小时......而且 MySQL 文档没有提到任何关于具有不同实现的表引擎(http://dev. mysql.com/doc/refman/5.0/en/group-by-optimization.html)。有谁知道为什么内部处理方式不同?

(注意:不,切换到 InnoDB 不是一个好的解决方案)谢谢

4

2 回答 2

3

尽管定义看似相同,但这两个表之间的区别在于 MyISAM 表是“堆”,而 InnoDB 表是聚集组织的表,例如聚集索引是表(通常是主键,(i)这里的索引)。

导致执行计划不同的另一个区别是,在 InnoDB 中,所有非聚集索引((n)在这种情况下是您的索引)也包括聚集索引的列,(i)在这种情况下,不需要全表扫描。

换句话说,(n)InnoDB 索引大致相当于一个(n, PK)MyISAM 索引。

MyISAM 引擎必须对索引进行全表扫描或索引扫描,(n)然后还要扫描表(以获取i列的值)。因此,它选择第一个计划(全扫描 + 文件排序来查找 MAX 值)。


(n, i)在 MyISAM 表中添加索引后,再次进行测试:

ALTER TABLE _test2_myisam
    ADD INDEX n_i (n, i) ;
于 2012-10-31T11:44:39.960 回答
0

This is because InnoDB are stored in an index-organized way, based on the primary key. So the table scan and the primary key scan will be the same exact thing. Unfortunately for MyISAM, this is not the case, it will have to do a filesort.

于 2012-10-31T11:39:36.003 回答