【问题标题】:MySQL GROUP BY optimization - InnoDB vs MyISAM?MySQL GROUP BY 优化 - InnoDB 与 MyISAM?
【发布时间】:2012-10-20 20:06:48
【问题描述】:

问题

有谁知道为什么基于 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 不是一个好的解决方案) 谢谢

【问题讨论】:

  • 这两个测试表具有相同的定义,除了使用的表引擎。当我运行测试时,这两个表中的数据也是相同的。还有什么我应该看的吗?
  • 在这一年和今天,几乎没有理由使用 MyISAM。引擎内部有自己的数据结构,并且可以做额外的工作,这样 MySQL 核心就不必这样做了。至于为什么 MyISAM 没有或确实有 - 您必须询问代码的创建者或咨询源代码。
  • “在这一天和这一年,几乎没有理由使用 MyISAM” MyISAM 有很多优点,而 InnoDB 没有。例如,我们构建了使用/严重依赖地理空间数据的移动应用程序。例如,表上的地理空间索引在 InnoDB 中不存在。而我们的服务/代码一直在利用它,因此获得了巨大的性能提升......
  • @Kristof:你说得对,这是 InnoDB 的两个限制之一:空间和全文搜索。
  • 全文存在,但是是的,地理空间索引不存在。我不会讨论如何实现类似的功能,但事实仍然是 InnoDB 在使用内存和 I/O 方面要好得多,并且做了很多工作,因此 MySQL 核心不必这样做。就我个人而言,我从未使用过地理空间索引或处理过地理空间数据,因此我在该领域不了解我的知识,因此我不推荐解决方法。

标签: mysql sql group-by query-optimization


【解决方案1】:

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

导致执行计划不同的另一个区别是,在 InnoDB 中,所有非聚集索引(在本例中为您的 (n) 索引)还包括聚集索引的列,在本例中为 (i) ,因此不需要全表扫描。

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

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


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

ALTER TABLE _test2_myisam
    ADD INDEX n_i (n, i) ;

【讨论】:

  • 基本上,(n) InnoDB 索引大致相当于(n, PK) MyISAM 索引。是不是更清楚了?
  • 是的,就是这样。基本上我们是在显式地模拟 InnoDB 在 MyISAM 表上的行为。谢谢:)
【解决方案2】:

这是因为 InnoDB 基于主键以索引组织方式存储。所以表扫描和主键扫描将是完全相同的事情。不幸的是,对于 MyISAM,情况并非如此,它必须进行文件排序。

【讨论】:

  • 对不起,这与主键无关。需要在二级索引上优化此 GROUP BY 查询。这就是 InnoDB 查询的结果显示“key”列的“i_n”的原因。也许测试查询让你感到困惑。如果我在 SELECT 中使用“MAX(t)”,我会得到相同的结果。
猜你喜欢
  • 2011-05-14
  • 1970-01-01
  • 2012-06-12
  • 2014-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多