【MySQL从入门到精通】【高级篇】(三十)记一次mysql5.7的新特性derived_merge的坑

news2024/11/16 15:15:55

您好,我是码农飞哥(wei158556),感谢您阅读本文,欢迎一键三连哦
💪🏻 1. Python基础专栏,基础知识一网打尽,9.9元买不了吃亏,买不了上当。 Python从入门到精通
❤️ 2.网上优质的Python题库很少,这里给大家推荐一款非常棒的Python题库,从入门到大厂面试题👉点击跳转刷题网站进行注册学习
❤️ 3. Python爬虫专栏,系统性的学习爬虫的知识点。9.9元买不了吃亏,买不了上当 。python爬虫入门进阶
❤️ 4. Ceph实战,从原理到实战应有尽有。 Ceph实战
❤️ 5. Java高并发编程入门,打卡学习Java高并发。 Java高并发编程入门
😁 6. 社区逛一逛,周周有福利,周周有惊喜。码农飞哥社区,飞跃计划

文章目录

    • 1. 项目场景
    • 2. 问题描述
    • 3. 原因分析
    • 4. 问题解决
      • 4.1. 方式一:关闭derived_merge特性
      • 4.2. 方式二:采用DISTINCT函数使得 derived_merge 参数合并派生类失效
    • 最后说一句
    • 参考
    • 总结

1. 项目场景

现有课堂活动评价的需求:教师对学生提交的活动进行评价, 教师可重复评价,即对同一个学生同一个活动进行多次评价,这种情况下需要取最新的那个评价。

2. 问题描述

本来期望直接使用 rank() over() 开窗函数,就像下面这样,但是奈何开窗函数只在mysql 8.0 及其以上的版本支持。

 rank() over(
        partition by activity_id,
         comment_open_id
        order by
          report_date desc
      ) RK

而项目组使用的是MySQL的版本是 5.7,此版本不支持开窗函数,故放弃此方案。
经过一番调研之后,决定采用子查询,在子查询中先按照时间report_date倒序排列,然后在外层查询中按照 activity_id+comment_open_id 分组,因为分组的话会取该分组中的第一条数据。
理想是丰满的,显示是骨感的!!!!
如下:原始数据有4条数据,其中第一条数据(id=11)和第四条数据(id=19)的活动ID(activity_id)和用户id(comment_open_id)都相同。按照我们期望的这两条数据只取id=19的那条数据,因为那条数据更新。而第二条数据和第三条数据正常保留。故期望的分组结果是 13,17,19 这三条数据。
在这里插入图片描述
第一步:子查询先按照时间排序,按照时间分组之后发现id=19的数据排在了id=11的数据前面

SELECT
	id,
	activity_id,
	activity_name,
	report_date,
	comment_open_id,
	logic_score
FROM
	t_student_five_activity_daily 
WHERE
	 comment_open_id = 'fbc284072a40da842efb24deacfa39d5d1baaccdbbe7b95e640d38eafa658b25149d78a0208f9a632c73eeeb30d1830e5f1a41f5964a8417' 
ORDER BY
	report_date DESC;

在这里插入图片描述
第二步:在外层查询中按照activity_id和comment_open_id 进行分组

SELECT a.* FROM
(
SELECT
	id,
	activity_id,
	activity_name,
	report_date,
	comment_open_id,
	logic_score
FROM
	t_student_five_activity_daily 
WHERE
	 comment_open_id = 'fbc284072a40da842efb24deacfa39d5d1baaccdbbe7b95e640d38eafa658b25149d78a0208f9a632c73eeeb30d1830e5f1a41f5964a8417' 
ORDER BY
	report_date DESC
) as a
GROUP BY 
  a.activity_id,
	a.comment_open_id

在这里插入图片描述
但是分组之后,我们发现最终取的结果是13,17,11 这三条数据,与我们期望的 13,17,19 有出入。
直觉告诉我们应该是子查询里面的排序没有生效,不然的话应该取的就是id=19那条数据

3. 原因分析

遇到数据库的SQL问题不要慌,首先查询一下执行计划。
在这里插入图片描述
执行计划显示只有一个表的处理,不对呀,应该是两张表,先子查询查出一张临时表,然后外层查询再从这张临时表筛选出一张新表,总共两张表才对。而是采用了临时表,磁盘排序的方式。这就说明查询优化器对我们的SQL进行了查询优化。

一番百度之后,发现其实是mysql5.7针对于5.6版本做了一个优化,针对mysql本身的优化器增加了一个控制优化器的参数叫 derived_merge ,什么意思呢,“派生类合并”。
什么意思呢,据mysql官方使用手册的说法:

在这里插入图片描述
这里将派生表合并到外部查询块中,就相当于嵌套子查询没啥鸟用了。
通过对mysql官方使用手册的了解,mysql5.7对 derived_merge 参数默认设置为on,也就是开启状态,当然我们也可以通过命令查看一下(在命令行窗口中执行该命令):

show variables like '%optimizer_switch%';

在这里插入图片描述

4. 问题解决

问题的原因找到了,那么解决问题就简单了,这里有两种方式来解决这个问题

4.1. 方式一:关闭derived_merge特性

我们在mysql5.7中把它关闭 shut downn 使用如下命令:

set  optimizer_switch='derived_merge=off';
set global optimizer_switch='derived_merge=off';

这样如果from中查询出来的的结果就不会与外部查询块合并了,sql执行结果如下:
在这里插入图片描述
SQL的执行计划如下:在执行计划中发现了两个查询id=2的就是子查询。
在这里插入图片描述
当然修改 derived_merge 参数得谨慎而行之,因为mysql5.7版本有了这个优化的机制是有它的道理的,之所以去除派生类与外部块合并,是因为减少查询开销,派生类是个临时表,开辟一个临时表的同时还要维护和排序或者分组,都会影响效率,所以尽量不要去修改此参数。
其实也有多种办法不需要修改 derived_merge 参数而使合并派生类失效,具体做法可参考官方使用手册, 摘抄手册文:

4.2. 方式二:采用DISTINCT函数使得 derived_merge 参数合并派生类失效

在子查询中使用DISTINCT函数,使得子查询不会被合并到外部查询块中。

SELECT a.* FROM
(
SELECT
  DISTINCT
	id,
	activity_id,
	activity_name,
	report_date,
	comment_open_id,
	logic_score
FROM
	t_student_five_activity_daily 
WHERE
	 comment_open_id = 'fbc284072a40da842efb24deacfa39d5d1baaccdbbe7b95e640d38eafa658b25149d78a0208f9a632c73eeeb30d1830e5f1a41f5964a8417' 
ORDER BY
	report_date DESC
) as a
GROUP BY 
  a.activity_id,
	a.comment_open_id;

查询结果如下所示:

在这里插入图片描述
执行计划如下所示:
在这里插入图片描述
当然处理DISTINCT函数以外,还有其他的函数也是可以的

可以通过在子查询中使用任何阻止合并的构造来禁用合并,尽管这些构造对实现的影响并不明确。 防止合并的构造对于派生表和视图引用是相同的:
1.聚合函数( SUM() , MIN() , MAX() , COUNT()等)
2.DISTINCT
3.GROUP BY
4.HAVING
5.LIMIT
6.UNION或UNION ALL
7.选择列表中的子查询
8.分配给用户变量
9.仅引用文字值(在这种情况下,没有基础表)

最后说一句

如果你使用的是MySQL 8.0及以上的版本,那么你可以直接使用开窗函数 rank() over()。参考SQL如下:

 SELECT a.* FROM
(
SELECT
	id,
	activity_id,
	activity_name,
	report_date,
	comment_open_id,
	logic_score,
	RANK() over(
	partition by activity_id,
         comment_open_id
        order by
          report_date desc
	) RK
FROM
	t_student_five_activity_daily 
WHERE
	 comment_open_id = 'fbc284072a40da842efb24deacfa39d5d1baaccdbbe7b95e640d38eafa658b25149d78a0208f9a632c73eeeb30d1830e5f1a41f5964a8417' 
) as a
WHERE a.RK=1

参考

记一次mysql5.7的新特性derived_merge的坑

总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/129096.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习 Day23——利用RNN实现天气预测

深度学习 Day23——利用RNN实现天气预测 文章目录深度学习 Day23——利用RNN实现天气预测一、前言二、我的环境三、前期工作1、导入依赖项2、导入数据3、查看数据基本信息4、查看各列数据的数据类型5、转换数据集中有关时间数据转换为时间格式6、删除Date标签列7、查看所有列的…

多版本并发控制(MVCC)

MVCC机制概述 MVCC(Multi-Version Concurrency Control),中文是多版本并发控制,是指在使用READ COMMITTED、REPEATABLE READ这两种隔离级别的事务在执行SELECT操作时访问记录的版本链的过程,从而在不加锁的前提下使不…

基于LSTM三分类的文本情感分析,采用LSTM模型,训练一个能够识别文本postive, neutral, negative三种

基于LSTM三分类的文本情感分析,采用LSTM模型,训练一个能够识别文本postive, neutral, negative三种 ,含数据集可直接运行 完整代码下载地址:基于LSTM三分类的文本情感分析 基于LSTM三分类的文本情感分析 背景介绍 文本情感分析…

Comic Life - 超棒的漫画制作工具,拥有多种动画模版,创作属于自己的漫画

Comic Life - 超棒的漫画制作工具,拥有多种动画模版,创作属于自己的漫画 Comic Life是一个照片编辑器,能够添加各种效果,并基于它们创建漫画。该工具包包括各种各样的模板,可以很容易地将照片放置在工作表上&#xff0…

CKEditor 为你的Flask项目添加一个富文本编辑器

人家高高在上的CKEditor是有个官网的!! WYSIWYG HTML Editor with Collaborative Rich Text EditingRock-solid, Free WYSIWYG Editor with Collaborative Editing, 200 features, Full Documentation and Support. Trusted by 20k companies.https://c…

SBM模型分析全流程

数据包络分析DEA时,其研究投入产出效率情况,并且其假定投入和产出之间存在单调线性关系,其为一种线性规划技术来确定DMU相对效率的方法。但有时候会多出下‘非期望产出’,就是不希望有它产出,比如资金投入、教育投入换…

【Unity3D日常开发】Unity3D拓展开发:UI界面控制,UI界面的显示和隐藏实现

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客QQ群:1040082875 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 在开发中,可能遇到管理…

2022最后一天盘点

今天是今年最后的一天工作日,对于我来说就是今年的最后一天,因为放假了我就不需要思考了(当然公司后端程序员要保持24小时oncall) 1 阳完之后 还是有些 咳嗽,公司此起彼伏的咳嗽声,不知道什么时候所有人都…

21.合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4] 示例 2: 输入:l1 [], l2 [] 输出:[…

【日常系列】LeetCode《23·回溯2》

数据规模->时间复杂度 <10^4 &#x1f62e;(n^2) <10^7:o(nlogn) <10^8:o(n) 10^8<:o(logn),o(1) 内容 lc 401 &#xff1a;二进制手表 https://leetcode.cn/problems/binary-watch/ 提示&#xff1a; 0 < turnedOn < 10 class Solution:def readBinary…

java jvm详解

java 系列文章之JVM 文章目录java 系列文章之JVM一、JVM1.基本概念2.运行过程二、线程三、JVM 内存区域1. 程序计数器(线程私有)2. 虚拟机栈(线程私有)3. 本地方法区(线程私有)4. 堆&#xff08;Heap-线程共享&#xff09;-运行时数据区5. 方法区/永久代&#xff08;线程共享&a…

UE4.27 C++调用DLL

1.首先在UE C项目中添加一个x64动态链接库&#xff0c;取名RouteInterface,放到Source下面&#xff1b; 2.在Source下面新建两个文件夹Include和Lisbs,这两个文件夹用来保存库的头文件和lib文件 3.在项目RouteInterface下面添加一个类&#xff1a;TestDll,并且把头文件保存到…

Mybatis-Plus查询投影与查询条件设置

目录 查询投影 查询指定字段 聚合查询 分组查询 查询条件设置 等值查询 范围查询 模糊查询 排序查询 查询投影 目前我们在查询数据的时候&#xff0c;什么都没有做默认就是查询表中所有字段的内容而查询投影即不查询所有字段&#xff0c;只查询出指定内容的数据 查询指…

九、文件File、IO流

文件File File可以用来表示计算机中的文件或者文件夹官方定义&#xff1a;文件和文件夹路径名的抽象表示形式 3种构造 1File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的File实例2File(String parent, String child) 从父路径名字符串和子路径名字…

2022硅谷大厂的大!失!败!AiDA时尚设计师助手;2023热门IT技能预告;Uber送货机器人;GitHub今日热榜 | ShowMeAI资讯日报

&#x1f440;日报合辑 | &#x1f3a1;AI应用与工具大全 | &#x1f514;公众号资料下载 | &#x1f369;韩信子 &#x1f4e2; 『抖音』2022抖音热点数据报告&#xff0c;共度温暖岁末 抖音热点联合巨量算数&#xff0c;发布了《2022抖音热点数据报告》&#xff0c;盘点了20…

如何在pycharm上安装tensorflow

TensorFlow™是一个基于数据流编程&#xff08;dataflow programming&#xff09;的符号数学系统&#xff0c;被广泛应用于各类机器学习&#xff08;machine learning&#xff09;算法的编程实现&#xff0c;其前身是谷歌的神经网络算法库DistBelief 。 Tensorflow拥有多层级结…

qt 崩溃处理

Windows系统MSVC编译器的dump文件 debug模式 生成exe自带生成pdb文件&#xff0c;所以无需处理。 1.生成dump文件 通过修改注册表&#xff0c;增加注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps 具体见&#xff1a;利用vs 分…

Forrester Wave发布最新报告 腾讯云数据连接器评分卓越

全球权威研究机构 Forrester 在2022年12月8日最新发布的《中国公有云开发和基础设施平台&#xff0c;Q4 2022》报告中&#xff0c;腾讯云获得高分&#xff0c;位列“领导者象限”。Forrester在报告中提出&#xff1a;“企业在进行公有云开发和基设施平台提供商的选项中&#xf…

php宝塔搭建部署实战帮管客CRM客户管理系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的帮管客CRM客户管理系统源码&#xff0c;感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&#xf…

商业智能BI中,业务质量分析和业务成本分析

最初谁也没有想到&#xff0c;信息化 、数字化技术及其应用能够在如此短时间内快速覆盖了社会的方方面面&#xff0c;如今人们的衣食住行和工作生活娱乐都离不开数字化、数据的身影。 数据分析&#xff0c;是离不开业务的&#xff0c;只有把业务研究好了&#xff0c;所做出的报…