The SUM() and AVG() functions return a DECIMAL value for exact-value arguments (integer or DECIMAL), and a DOUBLE value for approximate-value arguments (FLOAT or DOUBLE). (Before MySQL 5.0.3, SUM() and AVG() return DOUBLE for all numeric arguments.)
可是通过我们上面打印信息可以看到两个字段的长度加起来是19,而optimizer_trace里的tmp_table_info.reclength是20。通过其他尝试也发明table->s->reclength的长度就是table->field数组内里全部字段的字段长度和再加1。
总结执行流程
- 实行在堆上行使memory的内存姑且表来存放group by的数据,发明内存不足;
- 建设一张姑且表,姑且表上有两个字段,aid和num字段(sum(pv) as num);
- 从索引idx_day_aid_pv中取出1行,插入姑且表。插入法则是假如aid不存在则直接插入,假如存在,则把pv的值累加在num上;
- 轮回遍历索引idx_day_aid_pv上20181220~20181224之间的全部行,执行步调3;
- 对姑且表按照num的值做优先行列排序;
- 取出最后留在堆(优先行列的堆)内里的10行数据,作为功效集直接返回,不必要再回表;
增补声名优先行列排序执行步调说明:
- 在姑且表(未排序)中取出前 10 行,把个中的num和aid作为10个元素组成一个小顶堆,也就是最小的 num 在堆顶。
- 取下一行,按照 num 的值和堆顶值作较量,假如该字大于堆顶的值,则替代掉。然后将新的堆做堆排序。
- 一再步调2直到第 552203 行较量完成。
优化
方案1 行使 idx_aid_day_pv 索引
- # Query_time: 4.406927 Lock_time: 0.000200 Rows_sent: 10 Rows_examined: 1337315
- SET timestamp=1552791804;
- select aid,sum(pv) as num from article_rank force index(idx_aid_day_pv) where day>=20181220 and day<=20181224 group by aid order by num desc limit 10;
扫描行数都是1337315,为什么执行耗损的时刻上快了12倍呢?
索引示例
为了便于领略,,同样我也凭证索引的法则先模仿idx_aid_day_pv索引的一小部门数据
group by 不必要姑且表的环境
为什么机能上比 SQL1 高了,许多呢,缘故起因之一是idx_aid_day_pv索引上aid是确定有序的,那么执行group by的时辰,则不会建设姑且表,排序的时辰才必要姑且表。假如印证这一点呢,我们通过下面的执行打算就能看到
行使idx_day_aid_pv索引的结果:
- mysql> explain select aid,sum(pv) as num from article_rank force index(idx_day_aid_pv) where day>=20181220 and day<=20181224 group by aid order by null limit 10;
-
- +----+-------------+--------------+------------+-------+-------------------------------+----------------+---------+------+--------+----------+-------------------------------------------+
-
- | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
-
- +----+-------------+--------------+------------+-------+-------------------------------+----------------+---------+------+--------+----------+-------------------------------------------+
-
- | 1 | SIMPLE | article_rank | NULL | range | idx_day_aid_pv,idx_aid_day_pv | idx_day_aid_pv | 4 | NULL | 404607 | 100.00 | Using where; Using index; Using temporary |
-
- +----+-------------+--------------+------------+-------+-------------------------------+----------------+---------+------+--------+----------+-------------------------------------------+
留意我上面行使了order by null暗示逼迫对group by的功效不做排序。假如不加order by null,上面的 sql 则会呈现Using filesort (编辑:湖南网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|