Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/58.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中不在GROUPBY中的列,但我不能使用同等性能的列_Mysql_Optimization_Indexing_Group By - Fatal编程技术网

MySQL声称我可以使用SELECT中不在GROUPBY中的列,但我不能使用同等性能的列

MySQL声称我可以使用SELECT中不在GROUPBY中的列,但我不能使用同等性能的列,mysql,optimization,indexing,group-by,Mysql,Optimization,Indexing,Group By,MySQL文档指出,不管SQL标准怎么说,在SELECT子句中使用不在GROUPBY子句中的列是可以的,只要它们在功能上依赖于分组键 MySQL通过so扩展了GROUP的使用 您可以使用非聚集列 或选择列表中的计算 不显示在组中的 条款您可以使用此功能来 通过避免 不必要的列排序和 分组。例如,您不需要 组中的customer.name 以下查询: SELECT order.custid, customer.name, MAX(payments) FROM order,customer

MySQL文档指出,不管SQL标准怎么说,在SELECT子句中使用不在GROUPBY子句中的列是可以的,只要它们在功能上依赖于分组键

MySQL通过so扩展了GROUP的使用 您可以使用非聚集列 或选择列表中的计算 不显示在组中的 条款您可以使用此功能来 通过避免 不必要的列排序和 分组。例如,您不需要 组中的customer.name 以下查询:

SELECT order.custid, customer.name,
MAX(payments)   FROM order,customer  
WHERE order.custid = customer.custid  
GROUP BY order.custid;
标准 SQL,则必须添加 customer.name添加到GROUP BY子句。 在MySQL中,名称是多余的

听起来很合理。然而,尽管我可以选择这些列,但它似乎对性能有不利影响

EXPLAIN SELECT o.id FROM objects o GROUP BY o.id;
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | o     | range | NULL          | PRIMARY | 3       | NULL | 5262 | Using index for group-by |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
我意识到这个问题相当愚蠢;它只是具有相同问题的更复杂查询的最简单版本。当只选择I group by的主键ID时,MySQL使用主键索引。但是,当我包含其他列时,MySQL没有

EXPLAIN SELECT o.id, o.name FROM objects o GROUP BY o.id;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | o     | ALL  | NULL          | NULL | NULL    | NULL | 5261 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+

使用filesort而不是索引真的让我很沮丧。我目前希望从此表中选择*,因此希望避免重复组中的所有列并为它们编制索引。有没有办法让MySQL像我所期望的那样使用主键索引?

为group by使用一个派生表,然后重新连接到您想要从中选择的任何表上

,因为看起来没有一个简单的答案,所以我现在选择一个便宜的解决方案

我要做的事情如下:

SELECT o1.* FROM objects o1 WHERE o1.id IN (SELECT o2.id FROM objects o2 WHERE mycondition GROUP BY o2.id)
然而,根据解释,MySQL优化器认为子查询是依赖的,这总是一个非常非常糟糕的性能杀手。我认为这是查询优化器中的一个缺陷,因为它是同一个表,尽管它有别名。因此,我将使用一个查询来获取ID,并将它们放入第二个获取o.*的查询中。它具有合理的性能,并且不会太痛苦


这个问题仍然可以用更干净的解决方案来回答,这些解决方案即使没有更好的效果,也可以表现得更好:

在第一个查询中,您访问的唯一字段是索引,因此mysql只需查看索引文件。但是在第二个查询中,您现在从表本身提取一列,这也需要读取表数据。第一个查询并没有像使用WHERE子句那样使用主键索引。它只对groupby使用它,但它仍然在查看索引中的每个条目

第一个查询和第二个查询之间的区别在于,第二个查询必须查看完整表中的每一行,即表扫描,而不仅仅是索引中的每一个主键值

就优化而言,如果您的实际查询没有示例中的累积函数SUM、COUNT等,那么只需执行以下操作,您就会看到一个重大改进:

SELECT DISTINCT o.id, o.name FROM objects o

但是,如果您的简单示例中只有这样的情况,并且您的查询确实需要一个组,那么您的下一个最佳选择是增加变量,以允许同时在内存中容纳更多的行。

我可以在技术上使用子查询和派生表,但MySQL优化器至少以其当前形式存在,在Debian repositories的最新版本中,将它们视为依赖子查询,而不是提前运行然后运行的查询。我打赌这是因为它是同一张表,有不同的别名。