mysql 嵌套group by_MySQL数据库SQL优化之GROUP BY 语句和优化嵌套查询

本文介绍了如何优化MySQL中的GROUP BY语句,通过ORDER BY NULL避免Filesort操作提高性能。同时,讨论了如何用JOIN替换子查询以提升查询效率,特别是在存在合适索引的情况下,LEFT JOIN在某些场景下比NOT IN子查询更快。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.优化GROUP BY 语句

默认状况下,MySQL对全部GROUP BY col1,col2,...的字段进行排序。这与在查询中指定ORDER BY col1,col2,...相似。mysql

所以,若是显示包括一个包含相同列的order by 子句,则对MySQL的实际执行性能没什么影响。sql

若是查询包括group by 但用户想要避免排序结果的消耗,则能够指定order by null 禁止排序,以下面的例子:性能

mysql> explain select payment_date,sum(amount) from payment group by payment_date;

+----+-------------+---------+------------+------+---------------+------+---------+------+-------+----------+-----------------+

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

+----+-------------+---------+------------+------+---------------+------+---------+------+-------+----------+-----------------+

| 1 | SIMPLE | payment | NULL | ALL | NULL | NULL | NULL | NULL | 16125 | 100.00 | Using temporary,Using filesort |

+----+-------------+---------+------------+------+---------------+------+---------+------+-------+----------+-----------------+

1 row in set, 1 warning (0.04 sec)

mysql> explain select payment_date,sum(amount) from payment group by payment_date order by null;

+----+-------------+---------+------------+------+---------------+------+---------+------+-------+----------+-----------------+

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

+----+-------------+---------+------------+------+---------------+------+---------+------+-------+----------+-----------------+

| 1 | SIMPLE | payment | NULL | ALL | NULL | NULL | NULL | NULL | 16125 | 100.00 | Using temporary |

+----+-------------+---------+------------+------+---------------+------+---------+------+-------+----------+-----------------+

1 row in set, 1 warning (0.00 sec)

从上面的例子能够看出,第一个sql语句须要进行“Filesort”,而第二个SQL因为ORDER BY NULL 不须要进行“Filesort”,而上文提过Filesort 每每很是耗费时间。优化

可是,在个人MySQL 8.0中,两种方式查询没有区别。code

2.优化嵌套查询

MySQL 4.1开始支持SQL的子查询。这个技术可使用SELECT 语句来建立一个单例的查询结果,而后把这个结果做为开始过滤条件在用在另外一个查询中。排序

使用子查询能够一次性的完成不少逻辑上须要多个步骤才能完成的SQL操做,同时也能够避免事务或者表死锁。而且写起来也很容易。可是,有些状况下,子查询能够被更有效率的链接(JION)替代。索引

在下面的例子中,要从客户表customer 中找到不在支付表payment 中的全部客户信息:事务

mysql> explain select * from customer where customer_id not in (select customer_id from payment);

+----+--------------------+----------+------------+----------------+--------------------+--------------------+---------+------+------+----------+-------------+

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

+----+--------------------+----------+------------+----------------+--------------------+--------------------+---------+------+------+----------+-------------+

| 1 | PRIMARY | customer | NULL | ALL | NULL | NULL | NULL | NULL | 599 | 100.00 | Using where |

| 2 | DEPENDENT SUBQUERY | payment | NULL | index_subquery | idx_fk_customer_id | idx_fk_customer_id | 2 | func | 26 | 100.00 | Using index |

+----+--------------------+----------+------------+----------------+--------------------+--------------------+---------+------+------+----------+-------------+

2 rows in set, 1 warning (0.10 sec)

若是使用链接 JOIN 来完成这个查询工做,速度将会快不少。尤为是当payment 表中对customer_id 建有索引,性能将会更好,j具体查询以下:内存

mysql> explain select * from customer a left join payment b on a.customer_id = b.customer_id where b.customer_id is null;

+----+-------------+-------+------------+------+--------------------+--------------------+---------+----------------------+------+----------+-------------------------+

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

+----+-------------+-------+------------+------+--------------------+--------------------+---------+----------------------+------+----------+-------------------------+

| 1 | SIMPLE | a | NULL | ALL | NULL | NULL | NULL | NULL | 599 | 100.00 | NULL |

| 1 | SIMPLE | b | NULL | ref | idx_fk_customer_id | idx_fk_customer_id | 2 | sakila.a.customer_id | 26 | 100.00 | Using where; Not exists |

+----+-------------+-------+------------+------+--------------------+--------------------+---------+----------------------+------+----------+-------------------------+

2 rows in set, 1 warning (0.00 sec)

从执行计划中能够看出查询关联的类型从 index_subquery 调整为了ref ,在MySQL 5.5如下版本(包括5.5),子查询的效率仍是不如关联查询JOIN.it

链接JOIN 之因此更有效率一些,是由于MySQL 不须要再内存中建立临时表来完成这个逻辑上须要两个步骤的查询工做。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值