【问题标题】:MySQL GROUP BY query runs quickly, but not as VIEWMySQL GROUP BY 查询运行很快,但不如 VIEW
【发布时间】:2014-05-30 11:43:44
【问题描述】:

我在 MySQL 5.5 中有一个 700 万行的 InnoDB 表。我需要使用 GROUP BY 和 SUM 在视图中聚合表。我在 MySQL 文档中使用 EXPLAIN 研究了优化技巧,并确保我拥有正确的索引。

查询像普通的 SELECT(1.9 秒)一样运行良好 - 但是当我把它变成 VIEW 时,性能非常慢(14 秒)。我不确定我哪里出错了,或者我是否应该采取不同的方法。任何指针都非常感谢。

这是桌子;

-- MySQL 5.5.34

CREATE TABLE `reporting_email` (
  `id` int(11) NOT NULL DEFAULT '0',
  `report_date` varchar(10) NOT NULL,
  `module_id` int(11) NOT NULL,
  `country_id` int(11) NOT NULL,
  `email_platform` varchar(10) NOT NULL DEFAULT 'UNKNOWN',
  `sends` int(11) DEFAULT '0',
 PRIMARY KEY (`id`),
KEY `date_idx` (`report_date`),
KEY `grouping_idx` (`report_date`,`country_id`,`email_platform`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SELECT COUNT(*) FROM ma.reporting_email;
-- 6,868,104 records

这个查询运行很快;

SELECT
  report_date,
  country_id,
  email_platform,
  SUM(sends) AS total_sends
FROM ma.reporting_email
GROUP BY report_date, country_id, email_platform;
-- executes in 1.946 seconds

这是解释 - 我认为一切看起来都不错;

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, SIMPLE, reporting_email, index, , grouping_idx, 68, , 6860009, 

但是看看当我把查询变成 VIEW 时会发生什么;

CREATE VIEW ma.reporting_email_vw
AS
SELECT
  report_date,
  country_id,
  email_platform,
  SUM(sends) AS total_sends
FROM ma.reporting_email
GROUP BY report_date, country_id, email_platform;

SELECT * FROM ma.reporting_email_vw;
-- 14.4 seconds to run

现在运行需要 14 秒!这是解释;

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, PRIMARY, <derived2>, ALL, , , , , 19953, 
2, DERIVED, reporting_email, index, , grouping_idx, 68, , 6860009, 

【问题讨论】:

  • Mysql 视图丢失所有索引。
  • @ThinkDifferent 但是 jhonan 没有使用视图!?!?
  • @Strawberry 可能是我误解了这个问题,但他明确表示正常查询需要 1.9 秒,但现在更改为 VIEW 需要 14 秒
  • jhonan 没有使用视图。他们只是使用相同的查询来创建视图。
  • 然后他们从该视图中选择所有内容

标签: mysql view indexing group-by query-optimization


【解决方案1】:

来自MySQL Performance Blog

只要视图避免聚合,DISTINCT、GROUP BY、ORDER BY、 等,然后它可以使用MERGE算法。不幸的是,这意味着 任何显着复杂性的视图几乎总是使用 TEMPTABLE 算法。

当您从视图执行SELECT 时发生的情况是整个结果集被复制到一个临时表中(您可以在EXPLAIN 结果中看到这一点),然后您的查询过滤器将应用于临时表中的结果桌子和服务。

由于您没有对视图应用任何过滤器(没有WHERE 子句),因此您最好只运行原始查询而不是使用视图,以避免额外的步骤。

【讨论】:

  • 谢谢@MarcusAdams - 所以看起来虽然底层查询使用的是 GROUP BY 的索引,但当结果被复制到临时表以提供视图时,性能就会受到影响。说得通。数据的最终目的地是 Tableau,所以我想我会在 Tableau 中运行完整的 SELECT 查询,而不是从视图中选择。
  • @jhonan,MySQL 在视图方面还有很多优化工作要做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-11
  • 2012-08-21
  • 2017-11-07
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多