mysql:包含groupby的视图的效率

7tofc5zh  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(407)

事实上,我没能想出(或研究)一个解决这个问题的办法,这意味着我要么太笨了,看不懂这些文件,要么事实上这是一个复杂的问题。
在一个相当大的数据库中,我经常需要这样的查询:

SELECT ... WHERE condition GROUP BY something;

这需要几分之一秒的时间来完成。所以我把它放在一个Angular :

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

当我这么做的时候

SELECT * FROM view_x WHERE condition;

要花一分钟以上才能完成。现在很容易看出原因:在普通选择中,db引擎首先从数百万条记录中选择几百个结果,然后仅对匹配的记录进行聚合和分组。在使用视图时,它似乎首先对整个数据集进行求值,对所有内容进行聚合和分组,然后只返回满足条件的记录,并丢弃了代价高昂的其余记录。
是否有更智能的视图解决方案,或者每次都必须使用全选?
谢谢。
编辑:以下是视图的原始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

而在视图定义中,在GROUPBY子句之前使用where子句进行相同的select。
一些附加信息:查询产生9条记录。使用视图执行需要19秒。根据mysql workbench,使用直接查询需要0.000秒。
当我将直接查询中的where子句替换为查询末尾具有相同条件的having子句时,我将在与使用视图的查询相同的执行时间结束。
是的,我忘了分组中的一些栏目。把它们放进去,没什么区别。
最小示例(5秒执行时间):

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

在给定作业id的情况下产生2条记录

2hh7jdfx

2hh7jdfx1#

好吧,我做了显而易见的事情,让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

相关问题