MySQL:包含GROUP BY

时间:2018-08-31 07:23:45

标签: mysql view

我无法提出(或研究)此问题的解决方案,这意味着我要么太愚蠢而无法阅读文档,要么实际上是一个复杂的问题。

在一个相当大的数据库中,我经常需要这样的查询:

SELECT ... WHERE condition GROUP BY something;

这需要一秒钟的时间才能完成。所以我将其放在一个视图中:

CREATE VIEW view_x AS SELECT ... GROUP BY something;

那我什么时候做

SELECT * FROM view_x WHERE condition;

需要一分钟以上才能完成。现在,很容易明白为什么:在简单的SELECT中,数据库引擎首先从数百万个记录中选择数百个结果,然后仅对匹配的记录进行聚合和分组。使用视图时,似乎首先评估整个数据集,对所有数据进行汇总和分组,然后仅返回满足条件的记录,并丢弃计算成本高昂的其余记录。

是否有更智能的VIEW解决方案,还是每次都必须使用完整的SELECT?

谢谢。

编辑:这是该视图的原始SQL代码:

CREATE VIEW v_status1 AS SELECT                 
    FROM_UNIXTIME(J.ts_start) AS job_start,     
    J.id AS job_id, J.carrier, J.n_wafers,      
    count(W.id) AS n                            
    FROM job AS J                               
    JOIN wafer AS W ON J.id=W.job_id            
    GROUP BY J.carrier, J.n_wafers, W.status_id;

表作业:100k条记录,表晶片:2M条记录。

在以下查询之间进行比较:

SELECT * FROM v_status1 WHERE carrier LIKE 'W96L00%'; -- very slow

与VIEW定义中的相同SELECT相比,WHERE子句位于GROUP BY子句之前。

一些其他信息:查询产生9条记录。使用该视图需要19秒钟才能执行。根据MySQL Workbench的使用直接查询,需要0.000秒。

当在查询末尾用具有相同条件的HAVING子句替换直接查询中的WHERE子句时,我将在与使用视图的查询相同的执行时间结束。

是的,我忘记了GROUP BY部分中的某些列。将它们放进去并没有多大区别。

最小示例(执行时间为5秒):

CREATE VIEW v_status2 AS SELECT 
    job_id,                     
    status_id,                  
    count(id) AS n
    FROM wafer                  
    GROUP BY job_id, status_id;

在获得一些job_id的情况下产生2条记录

1 个答案:

答案 0 :(得分:0)

好吧,我做了显而易见的事情,并要求MySQL进行解释。输出如下。我的解释一直是我一直怀疑的:MySQL首先建立一个临时表,进行所有艰苦的工作,进行汇总和分组,然后仅选择与选择条件匹配的行。换句话说,MySQL不够智能,无法首先分析视图以找到可以有效剔除原始数据集并仅对其余记录进行处理的地方。

顺便说一句,这与联接和索引无关。您可以在任何足够大的两列表中看到效果。

id      select_type     table   type    possible_keys   key     key_len ref     rows    Extra
1       PRIMARY <derived2>      ALL     NULL    NULL    NULL    NULL    952929          Using where
2       DERIVED WS      index   PRIMARY ix_waferstatus_text     123     NULL    9       Using index; Using temporary; Using filesort
2       DERIVED W       ref     ix_wafer_job_id,wafer_ibfk_2    wafer_ibfk_2    5       jobwatch.WS.id  105881  Using where
2       DERIVED J       eq_ref  PRIMARY,job_ibkf_2      PRIMARY 4       jobwatch.W.job_id       1       Using where
2       DERIVED T       eq_ref  PRIMARY PRIMARY 4       jobwatch.J.tool_id      1