最新要闻
- 世界实时:BBBA德系“四兄弟”组合解散!宝沃中国申请破产
- 夏季必备:GLM夏季薄款七分/九分/长裤34.9元新低抄底
- 鸿星尔克请网友吃冰淇淋 获赞大气!宝马MINI感受下 环球消息
- 半年内5名机车网红车祸身亡 又见两只脚够不着地女骑:大货身旁疾驰
- 刘慈欣在联合国被“催更”:当年奥巴马连发两封邮件要新书 环球短讯
- 它强任它强,驾控随我心,斯巴鲁Crosstrek全新上市!
- 每日报道:本轮系列赛前两战,詹姆斯面对布鲁克斯防守打出14中7
- 不同档位DLSS对画面帧数的影响究竟有多大?看完秒懂|天天通讯
- 老人无牌无证驾驶老头乐从河南跑到江苏 还要周游全国
- 10分钟补能400km 理想首批4C超级充电站上线运营:女生也能拎得动-天天日报
- 腾讯起诉《王者荣耀》代练赢了:构成不正当竞争 获赔60万
- 马云被聘为香港大学荣誉教授:聘期三年|天天速看料
- 当前资讯!启动“盟圈”,开拓聚才引才“新阵地”
- 热文:推广央行数字货币,牙买加财政部出台激励计划
- 中国人民解放军陆军第九四七医院与咸阳职业技术学院签订校企合作协议 当前聚焦
- 每日快报!女子骑摩托车遇沉降路段摔倒遭碾压身亡 竟担主责:官方重申不服可上诉
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
MySQL Execution Plan--DISTINCT语句优化
问题描述
在很多业务场景中业务需要过滤掉重复数据,对于MySQL数据库可以有多种SQL写法能实现这种需求,如:
使用DISTINCT,如:
【资料图】
SELECT DISTINCT username FROM hotel_owner WHERE username IN ("user001","user002");
使用GROUP BY,如:
SELECT username FROM hotel_owner WHERE username IN ("user001","user002")GROUP BY username;
使用LIMIT 1,如:
SELECT username FROM( SELECT username FROM hotel_owner WHERE username = "user001" LIMIT 1) AS T1UNION ALLSELECT username FROM( SELECT username FROM hotel_owner WHERE username = "user002" LIMIT 1) AS T2
使用EXIST,如:
SELECT username FROM ( SELECT "user001" AS username UNION ALL SELECT "user002" AS username) AS T1WHERE EXISTS( SELECT username FROM hotel_owner AS T2 WHERE T1.username = T1.username)
使用临时变量、使用公共表达式+rownumber(MYSQL 8.0)等其他
当前hotel_owner表上有索引idx_username(username)
,针对上面两个用户的数据量为:
mysql> SELECT username,count(1) AS usercount -> FROM hotel_owner -> WHERE username IN ("user001","user002") -> GROUP BY username;+-------------+-----------+| username | usercount |+-------------+-----------+| user002 | 16455 || user001 | 18718 |+-------------+-----------+2 rows in set (0.02 sec)
上面4种SQL都能得到相同的执行结果,但查询性能相差50倍以上。
问题原因
MySQL Server架构可分为MySQL网络连接层、MySQL服务层、MySQL存储引擎层三层:
- MySQL网络连接层,负责处理客户端请求连接。
- MySQL服务层,负责解析SQL语句生成直接计划,由查询执行引擎与存储引擎层进行交互处理,将处理结果返回给客户端。
- MySQL存储引擎层,负责MySQL中数据的存储与提取,与底层系统文件进行交互。MySQL存储引擎是插件式的,服务器中的查询执行引擎通过接口与存储引擎进行通信,接口屏蔽了不同存储引擎之间的差异 。
MySQL查询处理流程如下:
由于MySQL架构的分层设计和不同存储引擎内部实现的差异性,MySQL服务层的查询优化器无法针对某个存储引擎进行定制开发,导致MySQL查询优化器在某些场景下无法生成"相对更优"的执行计划,需要研发人员"使用查询提示"或"改写SQL语句"来改变SQL语句的执行计划和提示SQL语句的执行效率。
通过MySQL内部工具profiling能清楚得到上面四种SQL语句的实际执行耗时:
*************************** 1. row ***************************Query_ID: 1Duration: 0.02456375 Query: SELECT DISTINCT usernameFROM hotel_ownerWHERE username IN ("user001","user002")*************************** 2. row ***************************Query_ID: 2Duration: 0.02770700 Query: SELECT usernameFROM hotel_ownerWHERE username IN ("user001","user002")GROUP BY username*************************** 3. row ***************************Query_ID: 3Duration: 0.00054050 Query: SELECT usernameFROM( SELECT username FROM hotel_owner WHERE username = "user001" LIMIT 1) AS T1UNION ALLSELECT usernameFROM( SELECT username FROM hotel_owner WHERE username = "user002" LIMIT 1) AS T2*************************** 4. row ***************************Query_ID: 4Duration: 0.00083600 Query: SELECT usernameFROM ( SELECT "user001" AS username UNION ALL SELECT "user002" AS username) AS T1WHERE EXISTS( SELECT username FROM hotel_owner AS T2 WHERE T1.username = T1.username)
DISTINCT
方式和GROUP BY
方式耗时接近,耗时分别为24ms和27ms。
LIMIT 1
方式和EXISTS
方式耗时接近,耗时分别为0.5毫秒和0.8ms。
其中DISTINCT
方式的执行计划和执行成本明细为:
mysql> DESC SELECT DISTINCT username -> FROM hotel_owner -> WHERE username IN ("user001","user002") \G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: hotel_owner partitions: NULL type: rangepossible_keys: idx_seq_usr,idx_username key: idx_username key_len: 152 ref: NULL rows: 66282 filtered: 100.00 Extra: Using where; Using index1 row in set, 1 warning (0.00 sec)mysql> SHOW PROFILE CPU,BLOCK IO,SWAPS FOR QUERY 1;+----------------------+----------+----------+------------+--------------+---------------+-------+| Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out | Swaps |+----------------------+----------+----------+------------+--------------+---------------+-------+| starting | 0.000065 | NULL | NULL | NULL | NULL | NULL || checking permissions | 0.000006 | NULL | NULL | NULL | NULL | NULL || Opening tables | 0.000017 | NULL | NULL | NULL | NULL | NULL || init | 0.000024 | NULL | NULL | NULL | NULL | NULL || System lock | 0.000007 | NULL | NULL | NULL | NULL | NULL || optimizing | 0.000008 | NULL | NULL | NULL | NULL | NULL || statistics | 0.000158 | NULL | NULL | NULL | NULL | NULL || preparing | 0.000018 | NULL | NULL | NULL | NULL | NULL || Sorting result | 0.000004 | NULL | NULL | NULL | NULL | NULL || executing | 0.000001 | NULL | NULL | NULL | NULL | NULL || Sending data | 0.024214 | NULL | NULL | NULL | NULL | NULL || end | 0.000003 | NULL | NULL | NULL | NULL | NULL || query end | 0.000007 | NULL | NULL | NULL | NULL | NULL || closing tables | 0.000004 | NULL | NULL | NULL | NULL | NULL || freeing items | 0.000021 | NULL | NULL | NULL | NULL | NULL || cleaning up | 0.000008 | NULL | NULL | NULL | NULL | NULL |+----------------------+----------+----------+------------+--------------+---------------+-------+16 rows in set, 1 warning (0.00 sec)
而LIMIT 1
方式的执行成本明细为:
mysql> DESC SELECT username -> FROM( -> SELECT username -> FROM hotel_owner -> WHERE username = "user001" -> LIMIT 1 -> ) AS T1 -> UNION ALL -> SELECT username -> FROM( -> SELECT username -> FROM hotel_owner -> WHERE username = "user002" -> LIMIT 1 -> ) AS T2 \G*************************** 1. row *************************** id: 1 select_type: PRIMARY table: partitions: NULL type: systempossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1 filtered: 100.00 Extra: NULL*************************** 2. row *************************** id: 2 select_type: DERIVED table: hotel_owner partitions: NULL type: refpossible_keys: idx_username key: idx_username key_len: 152 ref: const rows: 34788 filtered: 100.00 Extra: Using index*************************** 3. row *************************** id: 3 select_type: UNION table: partitions: NULL type: systempossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1 filtered: 100.00 Extra: NULL*************************** 4. row *************************** id: 4 select_type: DERIVED table: hotel_owner partitions: NULL type: refpossible_keys: idx_username key: idx_username key_len: 152 ref: const rows: 31494 filtered: 100.00 Extra: Using index4 rows in set, 1 warning (0.00 sec)mysql> SHOW PROFILE CPU,BLOCK IO,SWAPS FOR QUERY 3;+----------------------+----------+----------+------------+--------------+---------------+-------+| Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out | Swaps |+----------------------+----------+----------+------------+--------------+---------------+-------+| starting | 0.000099 | NULL | NULL | NULL | NULL | NULL || checking permissions | 0.000003 | NULL | NULL | NULL | NULL | NULL || checking permissions | 0.000004 | NULL | NULL | NULL | NULL | NULL || Opening tables | 0.000060 | NULL | NULL | NULL | NULL | NULL || init | 0.000066 | NULL | NULL | NULL | NULL | NULL || System lock | 0.000007 | NULL | NULL | NULL | NULL | NULL || optimizing | 0.000004 | NULL | NULL | NULL | NULL | NULL || optimizing | 0.000008 | NULL | NULL | NULL | NULL | NULL || statistics | 0.000083 | NULL | NULL | NULL | NULL | NULL || preparing | 0.000018 | NULL | NULL | NULL | NULL | NULL || executing | 0.000001 | NULL | NULL | NULL | NULL | NULL || Sending data | 0.000027 | NULL | NULL | NULL | NULL | NULL || statistics | 0.000005 | NULL | NULL | NULL | NULL | NULL || preparing | 0.000005 | NULL | NULL | NULL | NULL | NULL || optimizing | 0.000004 | NULL | NULL | NULL | NULL | NULL || optimizing | 0.000003 | NULL | NULL | NULL | NULL | NULL || statistics | 0.000044 | NULL | NULL | NULL | NULL | NULL || preparing | 0.000006 | NULL | NULL | NULL | NULL | NULL || executing | 0.000001 | NULL | NULL | NULL | NULL | NULL || Sending data | 0.000020 | NULL | NULL | NULL | NULL | NULL || statistics | 0.000004 | NULL | NULL | NULL | NULL | NULL || preparing | 0.000002 | NULL | NULL | NULL | NULL | NULL || executing | 0.000002 | NULL | NULL | NULL | NULL | NULL || Sending data | 0.000007 | NULL | NULL | NULL | NULL | NULL || executing | 0.000001 | NULL | NULL | NULL | NULL | NULL || Sending data | 0.000002 | NULL | NULL | NULL | NULL | NULL || end | 0.000002 | NULL | NULL | NULL | NULL | NULL || query end | 0.000007 | NULL | NULL | NULL | NULL | NULL || removing tmp table | 0.000002 | NULL | NULL | NULL | NULL | NULL || query end | 0.000001 | NULL | NULL | NULL | NULL | NULL || closing tables | 0.000001 | NULL | NULL | NULL | NULL | NULL || removing tmp table | 0.000003 | NULL | NULL | NULL | NULL | NULL || closing tables | 0.000001 | NULL | NULL | NULL | NULL | NULL || removing tmp table | 0.000002 | NULL | NULL | NULL | NULL | NULL || closing tables | 0.000009 | NULL | NULL | NULL | NULL | NULL || freeing items | 0.000021 | NULL | NULL | NULL | NULL | NULL || cleaning up | 0.000008 | NULL | NULL | NULL | NULL | NULL |+----------------------+----------+----------+------------+--------------+---------------+-------+37 rows in set, 1 warning (0.00 sec)
DISTINCT
方式和LIMIT 1
方式都使用索引,其中最大耗时差异在Sending data部分。
DISTINCT
方式的Sending data部分耗时:
| Sending data | 0.024214 | NULL | NULL | NULL | NULL | NULL |
LIMIT 1
方式的Sending data部分耗时:
| Sending data | 0.000027 | NULL | NULL | NULL | NULL | NULL || Sending data | 0.000020 | NULL | NULL | NULL | NULL | NULL || Sending data | 0.000007 | NULL | NULL | NULL | NULL | NULL |
差异原因:
DISTINCT
方式需要扫描所有满足WHERE条件的16455+18718条记录并将这些记录返回到MySQL Server层,由MySQL Server层负责数据去重处理(DISTINCT)并返回给客户端。LIMIT 1
方式针对每个子查询仅需要扫描到第1条满足WHERE条件的记录并将这些记录返回到MySQL Server层,由MySQL Server层负责数据合并(UNION ALL)并返回给客户端。
当满足WHERE条件的记录较少时,无论使用上述4种SQL种的任意1种方式都能快速返回结果,但随着满足WHERE条件的记录增多时,需要结合实际的业务需求和数据分布来编写"高效SQL"。
优化建议
在编写SQL语句时,不仅需要根据业务需求编写"正确SQL",还需要根据"实际数据分布"编写"高效SQL"。
关键词:
-
Appuploader安装指南
转载:http: kxdang com topic appuploader install html下载和安装appuploaderIOS开发工具官网地址& 160;http: www app
来源: MySQL Execution Plan--DISTINCT语句优化
Python函数与码复用
Appuploader安装指南
全志Uboot fdt修改DTS进行临时调试的方法
热门看点:ReactNative 打包发布 Android 应用
世界实时:BBBA德系“四兄弟”组合解散!宝沃中国申请破产
夏季必备:GLM夏季薄款七分/九分/长裤34.9元新低抄底
鸿星尔克请网友吃冰淇淋 获赞大气!宝马MINI感受下 环球消息
半年内5名机车网红车祸身亡 又见两只脚够不着地女骑:大货身旁疾驰
刘慈欣在联合国被“催更”:当年奥巴马连发两封邮件要新书 环球短讯
它强任它强,驾控随我心,斯巴鲁Crosstrek全新上市!
全球速看:打好软件国产化攻坚战,闪信科技面向人工智能和数字经济进行新一代升级
【快播报】DRF的权限组件(源码分析)
物联网常见协议之Amqp协议及使用场景解析 当前报道
每日报道:本轮系列赛前两战,詹姆斯面对布鲁克斯防守打出14中7
【财经分析】聚焦可持续转型升级 绿色债券领域蓬勃发展
【财经分析】供需趋松压力增大 铁矿石大幅下挫-全球观察
不同档位DLSS对画面帧数的影响究竟有多大?看完秒懂|天天通讯
老人无牌无证驾驶老头乐从河南跑到江苏 还要周游全国
10分钟补能400km 理想首批4C超级充电站上线运营:女生也能拎得动-天天日报
腾讯起诉《王者荣耀》代练赢了:构成不正当竞争 获赔60万
马云被聘为香港大学荣誉教授:聘期三年|天天速看料
全球即时看!项目播报 | 璞华×江苏鼎为云,打造数字化“采云链”体系,赋能新能源机电行业生态化
环球关注:Excel的列数如何用数字表示?
WCF教程_编程入门自学教程_菜鸟教程-免费教程分享 每日速看
当前资讯!启动“盟圈”,开拓聚才引才“新阵地”
热文:推广央行数字货币,牙买加财政部出台激励计划
中国人民解放军陆军第九四七医院与咸阳职业技术学院签订校企合作协议 当前聚焦
每日快报!女子骑摩托车遇沉降路段摔倒遭碾压身亡 竟担主责:官方重申不服可上诉
世界百事通!致敬《流浪地球2》国内首个类ChatGPT模型MOSS正式开源
画面过度拟真被质疑造假:《Unrecord》官方发布引擎录像自证清白_百事通
华为回应孟晚舟要去美国出差传言:纯属造谣
传小鹏P7接亲车队开辅助驾驶连环追尾 小鹏回应:拿普通事故抹黑
贵州:一片茶叶走出的乡村振兴路-速递
环球看点!发现有检查“黑车”司机扔下车跑了 留下一车乘客发呆
【GPT开发】人人都能用ChatGPT4.0做Avatar虚拟人直播
浅谈日出日落的计算方法以及替代工具 - 日出日落 API-精彩看点
这款产品,竟然用了二千多年才爆火?|世界最资讯
当前焦点!比亚迪李云飞:比亚迪今年要卖300万台车
德国玩家竟如此钟爱AMD显卡!销量超过NVIDIA几乎20% 每日速讯
青岛国家深远海绿色养殖试验区养殖鱼类首次成功度夏-天天快讯
环球观点:尚无特效药!国产带状疱疹疫苗全国接种启动:一针能管10年
半价手慢无:卜珂巧克力夹心蛋卷14.9元/3罐 速递
电影情节成真!加拿大机场1.6吨黄金被盗 价值超亿美元_世界快讯
上演“史诗级灾难公关”:宝马蒸发市值可买约5亿个冰淇淋
可以再等等!iQOO 12系列在路上:200W超快闪充-天天新资讯
香菜饼最简单的做法,只需一把香菜,2个鸡蛋!
焦点热门:AIGC的阿克琉斯之踵
超过50多个热门的免费可用 API 分享|滚动
火山引擎 DataTester 3 大功能升级:聚焦敏捷、智能与易用,帮助企业降本增效
天天热讯:三峡艺术高中分数线(三峡艺术高中)
新华指数|钢“财”说:库存延续下行,基本面仍待改善|今日要闻
环球热点!长峰医院火灾系医院内部施工引燃可燃涂料所致
榴莲批发价1斤低至20元:海南国产榴莲也快上市了
2023新款超轻超弹:匹克轻弹风逸跑鞋119元狂促(原价249元)
《惊奇队长2》创纪录!62万踩成漫威最讨人厌的预告
男子被贴膏药秒倒地 官方通报:涉事膏药无迷药成分
驾驶舱可变大床!五菱龙卡本月上市:横竖都能拉
天语e66怎么开机?天语e66手机可以拍视频吗?
华为T8951什么时候上市的?华为T8951手机参数
中兴v987是什么型号?中兴V987手机参数
七月未央作者_七月未央
三星S3850如何恢复出厂设置?三星S3850手机参数
摩托罗拉MT620上市价格是多少?摩托罗拉MT620手机参数
C#写一套最全的SQL server帮助类(包括增删改查)
秦都区吴办吴家堡社区新时代文明实践站开展党建引领 “童”行同乐活动
热点!110万的比亚迪大把人买!仰望U8预售48小时:订单已超1.3万份
NVIDIA大失所望:RTX 4070卖崩了!AMD成市场赢家
天天资讯:用户自驾突发紧急情况!最后用华为P60 Pro获救:用一次续一生
五一假期十大热门城市:看看有你想去的吗?
升空后人工引爆!下次再来 成功三分之一的Starship 新动态
长安C401将被称为长安辛特克斯动力来自马自达1.6 天天微资讯
JS中的进程和线程-动态
linux下查看文件内容工具发布啦!
04 设置工作模式与环境(下)收集信息
天天速讯:全国首单绿色及能源保供双主题ABS在深交所完成发行
环球速讯:园企智推官“我为企业代言”推介大赛开启
全球通讯!苹果版余额宝收益4%?我可一点都不羡慕 背后有猫腻
世界视讯!你信吗?宝马MINI再道歉:吃冰淇淋的“老外”是同事 求宽容2位小姐姐
1499元起!荣耀X50i手机发布:标配256GB超大存储
环球快资讯:我国天文学家为银河系精确“称重”:约为8050亿个太阳质量
高速上惊现喷气式汽车 车尾一路滚滚浓烟 涡轮增压器坏了
海南省白沙县2023-04-20 12:36发布雷电黄色预警
MYSQL---主从同步概述与配置
Docker基础知识和命令使用入门
网络流的C++代码实现与过程讲解
每日关注!南昌大学举办潘际銮教育思想研讨会
伛偻提携往来而不绝者滁人游也翻译_伛偻提携_焦点热文
嫁入豪门?前世界首富目不转睛盯着谷爱凌,搂着爱凌合影很兴奋
绿色转型湾区“债”持续——中央结算公司2023年二季度债市研判六人谈举行
“星级酒店”旅游专列今日发车:双人大床房 24小时管家
暗黑4再次公测
当前速读:上海一商场特斯拉展车喇叭响不停 销售员束手无策 路人纷纷堵耳
华为实现自主可控的MetaERP研发:我们已经突破封锁 我们活了下来-环球速看
环球即时:德国男单全军覆没!世界冠军1:3输球,世界第六现场脱衣服换球服
双鱼座今日运势_双鱼座男生讨厌女生_今日看点
四大证券报精华摘要:4月21日
仰望U8市区上路 体型硕大:一旁70万的途锐秒变高尔夫
马斯克不止星舰发射失败 特斯拉暴跌近10%:市值一夜蒸发3780亿元
全球视讯!剧情够毁灭!漫威宣布《复仇5》 明年开拍:国人不爱看 不符合文化观?