Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL是否消除了SELECT和HAVING/GROUPBY子句之间的公共子表达式_Mysql_Group By_Query Optimization_Having - Fatal编程技术网

MySQL是否消除了SELECT和HAVING/GROUPBY子句之间的公共子表达式

MySQL是否消除了SELECT和HAVING/GROUPBY子句之间的公共子表达式,mysql,group-by,query-optimization,having,Mysql,Group By,Query Optimization,Having,我经常看到人们用这样的查询来回答MySQL问题: SELECT DAY(date), other columns FROM table GROUP BY DAY(date); SELECT somecolumn, COUNT(*) FROM table HAVING COUNT(*) > 1; 我总是喜欢给列一个别名,并引用GROUPBY或HAVING子句中的别名,例如 SELECT DAY(date) AS day, other columns FROM table GROUP BY

我经常看到人们用这样的查询来回答MySQL问题:

SELECT DAY(date), other columns
FROM table
GROUP BY DAY(date);

SELECT somecolumn, COUNT(*)
FROM table
HAVING COUNT(*) > 1;
我总是喜欢给列一个别名,并引用GROUPBY或HAVING子句中的别名,例如

SELECT DAY(date) AS day, other columns
FROM table
GROUP BY day;

SELECT somecolumn, COUNT(*) AS c
FROM table
HAVING c > 1;
MySQL是否足够聪明,可以注意到后面的子句中的表达式与SELECT中的表达式相同,并且只执行一次?我不知道如何测试这个-解释没有显示任何区别,但它似乎没有显示它是如何进行分组或过滤放在首位;它似乎主要用于优化连接和WHERE子句


我倾向于对MySQL优化持悲观态度,因此我愿意尽我所能帮助它。

我认为这可以通过使用睡眠功能进行测试, 例如,请看此演示:

两个查询的执行时间约为3000毫秒3秒。 表中有3条记录,对于每条记录,查询只休眠1秒,
因此,这意味着每个记录只对表达式求值一次,而不是两次。

在咨询一位MySQL工程师后,我给出了这个冗长的答案

缓存-不会“记住”查询的任何部分,以供以后在该查询或后续查询中使用。对比:查询缓存。 公共子表达式消除-否。这是一种常见的编译器技术,但MySQL不使用它。示例:a-b*a-b将进行两次减法运算。 从循环中删除常量-是,有限制。这是另一种编译器技术。 各种以SQL为中心的黑客——是的;见下文。 重新计算子查询-视情况而定。此外,优化器也在逐步改进。 视图-视情况而定。在某些情况下,视图的性能仍将比等效的SELECT更差。示例:没有条件下推到视图中的联合中。实际上,这更多的是一个行动延迟的问题。 我认为一些较新版本的MariaDB有一个子查询缓存。 警告:我对我的任何答案都没有100%的信心,但我相信大部分答案都是正确的,比如MySQL 5.7、MariaDB 10.1等等

将多行选择视为循环。许多,也许所有,确定性表达式只计算一次。示例:常数日期表达式,甚至包括函数调用。但是

NOW在查询开始时专门计算一次。此外,复制时会将值传递给从属对象。也就是说,当查询存储在从机上时,现在可能已经过时了。SYSDATE是另一种动物

特别是随着只出现了_full _group _by,group by需要知道它是否匹配SELECT表达式。因此,这将查找类似的代码

与WHERE和GROUP BY不同,HAVING和ORDER BY可以使用选择列表中的别名。所以选择expr作为x。。。拥有expr似乎要重新评估expr,但选择expr作为x。。。使用x似乎可以得到已经计算过的表达式

MariaDB 10.2的窗口功能在哪些地方可以/不能重用有一些非常严格的限制;我还没有他们的全貌


通常,这些都无关紧要——对表达式DATEdate甚至COUNT*的重新计算将得到相同的答案。此外,在行中进行搜索通常比表达式求值要昂贵得多。因此,除非你有一个好的秒表,否则你不会说出区别。

以防万一,你需要一个即时的答案,作为权宜之计,直到我能找到一个权威的引用,我怀疑它可能来自源代码,我非常确定解析器能够识别对确定性函数的调用,事实上,表达式并缓存结果,以便在查询中重用。+1这是一个连贯而有用的问题!巴尔马问了个问题?我担心我的指南针已经不可逆转地失去了平衡。函数结果被缓存这一事实的一个简单证明是——由于结果列确实已排序,MySQL对RAND的两个调用都使用了相同的值。我正试图根据优化器源代码得出一个稍微更权威的答案——我认为这一点现在值得一提。进一步的“证据”是当您将其中一个睡眠更改为2时。现在需要9秒。选择x+sleep1,按x+sleep1从t组中计数*需要6秒。会发生什么?可能原始示例只是转换为从t中选择不同的x+sleep1。另外:从t中选择x+sleep1作为c,c>0也需要6秒。所以我猜,每个别名在内部都会被它后面的表达式替换,并且每次都会重新计算。但是。。。睡眠并不是决定性的。SQRT是;兰德公司不是——因此,SQRT可以被记住,但兰德公司可能不会。OTOH,现在被故意记住了,但SYSDATE没有。考虑到另一个答案中的演示,这是否意味着它认为SLEEP1是一个确定性表达式,所以它只对它求值一次?确定性-否。否则查询将花费1秒,而不是3秒。我认为x+sleep1属于我在GROUP BY上说的黄鼠狼话 . 注意,x+sleep2分组需要9秒;通过检查,我不知道x是否参与了唯一的完整组。
Select * FROM t;

| X |
|---|
| 1 |
| 2 |
| 2 |

SELECT x+sleep(1)
FROM t
GROUP BY x+sleep(1);

SELECT x+sleep(1) As name
FROM t
GROUP BY name;