mysql group by如何优化?

面试题~

1 个回答

  • java小王子
    遇见错的人会消耗你,遇见对的人会治愈你。
    ### MySQL 中 `GROUP BY` 的优化 在 MySQL 中,`GROUP BY` 语句经常会涉及临时表和排序操作。以下是一些优化 `GROUP BY` 操作的具体方法和示例。 ### 示例表结构和数据 ```sql CREATE TABLE `t1` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `a` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- 插入示例数据 INSERT INTO t1 (id, a, b) VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3), ..., (1000, 1000, 1000); ``` ### 初始查询和执行计划 ```sql EXPLAIN SELECT id%10 AS m, COUNT(*) AS c FROM t1 GROUP BY m LIMIT 10; ``` 执行计划显示: - `using index`:使用覆盖索引 - `using temporary`:使用了内存临时表 - `using filesort`:使用了排序操作 ### `GROUP BY` 的执行过程 1. **创建内存临时表**:内存表包含两个字段 m 和 c,主键是 m。 2. **扫描表索引**:扫描表 `t1` 的索引 `a`,取出叶子节点上的 `id` 值,计算 `id%10` 的结果。 3. **插入或更新临时表**: - 如果临时表中没有主键为 `x` 的行,插入记录 `(x, 1)`。 - 如果有主键为 `x` 的行,将 `c` 值加 1。 4. **排序和返回结果**:根据字段 `m` 做排序,返回结果集。 ### 优化方法 #### 1. 使用 `ORDER BY NULL` 在 `GROUP BY` 语句末尾添加 `ORDER BY NULL`,可以避免自动排序过程,减少排序开销。 ```sql EXPLAIN SELECT id%10 AS m, COUNT(*) AS c FROM t1 GROUP BY m ORDER BY NULL; ``` 执行计划中 `using filesort` 已经消失,减少了排序开销。 #### 2. 创建索引 创建一个合适的索引,可以避免使用临时表。 ```sql ALTER TABLE t1 ADD COLUMN z INT GENERATED ALWAYS AS (id % 10), ADD INDEX (z); EXPLAIN SELECT z AS m, COUNT(*) AS c FROM t1 GROUP BY z; ``` 通过创建计算列 `z` 及索引,可以使 `GROUP BY` 操作利用索引,避免使用临时表。 #### 3. 使用 `SQL_BIG_RESULT` 提示 对于大数据量的 `GROUP BY` 操作,使用 `SQL_BIG_RESULT` 提示,直接使用磁盘临时表,避免内存不足导致性能下降。 ```sql EXPLAIN SELECT SQL_BIG_RESULT id%10 AS m, COUNT(*) AS c FROM t1 GROUP BY m; ``` ### `GROUP BY` 逻辑优化 1. **索引优化**: - 如果数据列上有索引,并且 `GROUP BY` 使用该列,则不需要临时表。 - 例如,新增 `z` 列并创建索引。 2. **磁盘排序**: - 如果数据量大,内存临时表不足以保存排序结果,可以使用 `SQL_BIG_RESULT` 提示。 ### 总结 通过索引优化、使用 `ORDER BY NULL` 和 `SQL_BIG_RESULT` 提示,可以显著提升 `GROUP BY` 操作的性能。理解 `GROUP BY` 的执行过程及其依赖的临时表,可以帮助我们制定更有效的优化策略。 ### 示例代码和执行计划 ```sql -- 创建计算列和索引 ALTER TABLE t1 ADD COLUMN z INT GENERATED ALWAYS AS (id % 10), ADD INDEX (z); -- 优化查询 EXPLAIN SELECT z AS m, COUNT(*) AS c FROM t1 GROUP BY z; -- 使用 ORDER BY NULL 避免排序 EXPLAIN SELECT id%10 AS m, COUNT(*) AS c FROM t1 GROUP BY m ORDER BY NULL; -- 使用 SQL_BIG_RESULT 提示 EXPLAIN SELECT SQL_BIG_RESULT id%10 AS m, COUNT(*) AS c FROM t1 GROUP BY m; ``` 优化后的查询可以显著减少 `GROUP BY` 操作的开销,提高查询性能。在大数据量场景下,选择合适的优化策略尤为重要。
    编辑于 2024-02-24 19:29 •IP属地 青海
    举报
    评论
    收藏