我的这篇博客出自我的博客园,原文地址:http://www.cnblogs.com/tangyanbo/p/4462734.html
今天放到iteye来和大家分享
补充:看到这么多朋友对sql优化感兴趣,我又重新补充了下文章的内容,将更多关于sql优化的知识分享出来,
喜欢这篇文章的朋友给个赞吧,哈哈,欢迎交流,共同进步。
2015-4-30补充:非常感觉编辑的推荐,同时又对慢查询语句优化了一遍,并附上优化记录,欢迎阅读文章。
场景
我用的数据库是mysql5.6,下面简单的介绍下场景
课程表
create table Course( c_id int PRIMARY KEY, name varchar(10) )
数据100条
学生表:
create table Student( id int PRIMARY KEY, name varchar(10) )
数据70000条
学生成绩表SC
CREATE table SC( sc_id int PRIMARY KEY, s_id int, c_id int, score int )
数据70w条
查询目的:
查找语文考100分的考生
查询语句:
select s.* from Student s where s.s_id in (select s_id from SC sc where sc.c_id = 0 and sc.score = 100 )
执行时间:30248.271s
晕,为什么这么慢,先来查看下查询计划:
EXPLAIN select s.* from Student s where s.s_id in (select s_id from SC sc where sc.c_id = 0 and sc.score = 100 )
发现没有用到索引,type全是ALL,那么首先想到的就是建立一个索引,建立索引的字段当然是在where条件的字段。
先给sc表的c_id和score建个索引
CREATE index sc_c_id_index on SC(c_id);
CREATE index sc_score_index on SC(score);
再次执行上述查询语句,时间为: 1.054s
快了3w多倍,大大缩短了查询时间,看来索引能极大程度的提高查询效率,建索引很有必要,很多时候都忘记建
索引了,数据量小的的时候压根没感觉,这优化的感觉挺爽。
但是1s的时间还是太长了,还能进行优化吗,仔细看执行计划:
查看优化后的sql:
SELECT `YSB`.`s`.`s_id` AS `s_id`, `YSB`.`s`.`name` AS `name` FROM `YSB`.`Student` `s` WHERE < in_optimizer > ( `YSB`.`s`.`s_id` ,< EXISTS > ( SELECT 1 FROM `YSB`.`SC` `sc` WHERE ( (`YSB`.`sc`.`c_id` = 0) AND (`YSB`.`sc`.`score` = 100) AND ( < CACHE > (`YSB`.`s`.`s_id`) = `YSB`.`sc`.`s_id` ) ) ) )
补充:这里有网友问怎么查看优化后的语句
方法如下:
有type=all
按照我之前的想法,该sql的执行的顺序应该是先执行子查询
select s_id from SC sc where sc.c_id = 0 and sc.score = 100
耗时:0.001s
得到如下结果:
然后再执行
select s.* from Student s where s.s_id in(7,29,5000)
耗时:0.001s
这样就是相当快了啊,Mysql竟然不是先执行里层的查询,而是将sql优化成了exists子句,并出现了EPENDENT SUBQUERY,
mysql是先执行外层查询,再执行里层的查询,这样就要循环70007*8次。
那么改用连接查询呢?
SELECT s.* from Student s INNER JOIN SC sc on sc.s_id = s.s_id where sc.c_id=0 and sc.score=100
这里为了重新分析连接查询的情况,先暂时删除索引sc_c_id_index,sc_score_index
执行时间是:0.057s
效率有所提高,看看执行计划:
这里有连表的情况出现,我猜想是不是要给sc表的s_id建立个索引
CREATE index sc_s_id_index on SC(s_id);
show index from SC
在执行连接查询
时间: 1.076s,竟然时间还变长了,什么原因?查看执行计划:
优化后的查询语句为:
SELECT `YSB`.`s`.`s_id` AS `s_id`, `YSB`.`s`.`name` AS `name` FROM `YSB`.`Student` `s` JOIN `YSB`.`SC` `sc` WHERE ( ( `YSB`.`sc`.`s_id` = `YSB`.`s`.`s_id` ) AND (`YSB`.`sc`.`score` = 100) AND (`YSB`.`sc`.`c_id` = 0) )
貌似是先做的连接查询,再进行的where条件过滤
回到前面的执行计划:
这里是先做的where条件过滤,再做连表,执行计划还不是固定的,那么我们先看下标准的sql执行顺序:
正常情况下是先join再进行where过滤,但是我们这里的情况,如果先join,将会有70w条数据发送join做操,因此先执行where
过滤是明智方案,现在为了排除mysql的查询优化,我自己写一条优化后的sql
SELECT s.* FROM ( SELECT * FROM SC sc WHERE sc.c_id = 0 AND sc.score = 100 ) t INNER JOIN Student s ON t.s_id = s.s_id
即先执行sc表的过滤,再进行表连接,执行时间为:0.054s
和之前没有建s_id索引的时间差不多
查看执行计划:
先提取sc再连表,这样效率就高多了,现在的问题是提取sc的时候出现了扫描表,那么现在可以明确需要建立相关索引
CREATE index sc_c_id_index on SC(c_id);
CREATE index sc_score_index on SC(score);
再执行查询:
SELECT s.* FROM ( SELECT * FROM SC sc WHERE sc.c_id = 0 AND sc.score = 100 ) t INNER JOIN Student s ON t.s_id = s.s_id
执行时间为:0.001s,这个时间相当靠谱,快了50倍
执行计划:
我们会看到,先提取sc,再连表,都用到了索引。
那么再来执行下sql
SELECT s.* from Student s INNER JOIN SC sc on sc.s_id = s.s_id where sc.c_id=0 and sc.score=100
执行时间0.001s
执行计划:
这里是mysql进行了查询语句优化,先执行了where过滤,再执行连接操作,且都用到了索引。
2015-04-30日补充:最近又重新导入一些生产数据,经测试发现,前几天优化完的sql执行效率又变低了
调整内容为SC表的数据增长到300W,学生分数更为离散。
先回顾下:
show index from SC
执行sql
SELECT s.* from Student s INNER JOIN SC sc on sc.s_id = s.s_id where sc.c_id=81 and sc.score=84
执行时间:0.061s,这个时间稍微慢了点
执行计划:
这里用到了intersect并集操作,即两个索引同时检索的结果再求并集,再看字段score和c_id的区分度,
单从一个字段看,区分度都不是很大,从SC表检索,c_id=81检索的结果是70001,score=84的结果是39425
而c_id=81 and score=84 的结果是897,即这两个字段联合起来的区分度是比较高的,因此建立联合索引查询效率
将会更高,从另外一个角度看,该表的数据是300w,以后会更多,就索引存储而言,都是不小的数目,随着数据量的
增加,索引就不能全部加载到内存,而是要从磁盘去读取,这样索引的个数越多,读磁盘的开销就越大,因此根据具体
业务情况建立多列的联合索引是必要的,那么我们来试试吧。
alter table SC drop index sc_c_id_index; alter table SC drop index sc_score_index; create index sc_c_id_score_index on SC(c_id,score);
执行上述查询语句,消耗时间为:0.007s,这个速度还是可以接收的
执行计划:
该语句的优化暂时告一段落
总结:
1.mysql嵌套子查询效率确实比较低
2.可以将其优化成连接查询
3.连接表时,可以先用where条件对表进行过滤,然后做表连接
(虽然mysql会对连表语句做优化)
4.建立合适的索引,必要时建立多列联合索引
5.学会分析sql执行计划,mysql会对sql进行优化,所以分析执行计划很重要
索引优化
上面讲到子查询的优化,以及如何建立索引,而且在多个字段索引时,分别对字段建立了单个索引
后面发现其实建立联合索引效率会更高,尤其是在数据量较大,单个列区分度不高的情况下。
单列索引
查询语句如下:
select * from user_test_copy where sex = 2 and type = 2 and age = 10
索引:
CREATE index user_test_index_sex on user_test_copy(sex); CREATE index user_test_index_type on user_test_copy(type); CREATE index user_test_index_age on user_test_copy(age);
分别对sex,type,age字段做了索引,数据量为300w,查询时间:0.415s
执行计划:
发现type=index_merge
这是mysql对多个单列索引的优化,对结果集采用intersect并集操作
多列索引
我们可以在这3个列上建立多列索引,将表copy一份以便做测试
create index user_test_index_sex_type_age on user_test(sex,type,age);
查询语句:
select * from user_test where sex = 2 and type = 2 and age = 10
执行时间:0.032s,快了10多倍,且多列索引的区分度越高,提高的速度也越多
执行计划:
最左前缀
多列索引还有最左前缀的特性:
执行一下语句:
select * from user_test where sex = 2 select * from user_test where sex = 2 and type = 2 select * from user_test where sex = 2 and age = 10
都会使用到索引,即索引的第一个字段sex要出现在where条件中
索引覆盖
就是查询的列都建立了索引,这样在获取结果集的时候不用再去磁盘获取其它列的数据,直接返回索引数据即可
如:
select sex,type,age from user_test where sex = 2 and type = 2 and age = 10
执行时间:0.003s
要比取所有字段快的多
排序
select * from user_test where sex = 2 and type = 2 ORDER BY user_name
时间:0.139s
在排序字段上建立索引会提高排序的效率
create index user_name_index on user_test(user_name)
最后附上一些sql调优的总结,以后有时间再深入研究
1. 列类型尽量定义成数值类型,且长度尽可能短,如主键和外键,类型字段等等
2. 建立单列索引
3. 根据需要建立多列联合索引
当单个列过滤之后还有很多数据,那么索引的效率将会比较低,即列的区分度较低,
那么如果在多个列上建立索引,那么多个列的区分度就大多了,将会有显著的效率提高。
4. 根据业务场景建立覆盖索引
只查询业务需要的字段,如果这些字段被索引覆盖,将极大的提高查询效率
5. 多表连接的字段上需要建立索引
这样可以极大的提高表连接的效率
6. where条件字段上需要建立索引
7. 排序字段上需要建立索引
8. 分组字段上需要建立索引
9. Where条件上不要使用运算函数,以免索引失效
参考文章
http://www.cnblogs.com/linfangshuhellowored/p/4430293.html
慢sql查询
http://tech.meituan.com/mysql-index.html
笛卡尔乘积
http://www.cnblogs.com/Toolo/p/3634563.html
sql优化
http://www.cnblogs.com/mliang/p/3637937.html
http://www.cnblogs.com/xwdreamer/archive/2012/07/19/2599494.html
执行计划参考:
http://www.cnblogs.com/ggjucheng/archive/2012/11/11/2765237.html
相关推荐
项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用
内容概要:本文档提供了关于数据分析全面的知识介绍与实战资源链接。首先,在数据分析的基础教程部分讲述了使用Python以及R两种语言来进行实际的数据分析工作所需具备的各项基本技能。其次,进阶教程涵盖从机器学习到深度学习的概念及其Python具体应用场景。接着,在工具有效利用层面介绍了多种热门库与平台的作用特点。在项目实践中,列举了四个实战案例:Titanic幸存者预测、房价预测、社交媒体情感倾向分析以及市场顾客购买模式研究,每个项目都有详细的技术流程指引。另外列出多个外部网站资源供进一步提升学习。 适用人群:本文主要面向有志于从事数据挖掘工作的学生和技术爱好者,同时也可辅助在职人士自我能力进阶。无论是在学术科研还是实际业务需求环境中都值得研读。 使用场景及目标:学习者将能够获取到系统的理论知识体系,熟悉业界主流软件包的功能优势,掌握具体业务问题解决方案路径,提高自身的综合技术素质,从而为个人职业规划增添竞争力。 其他说明:文档里推荐了不少高质量参考资料和实用线上学习社区,能有效补充专业知识空白并促进社交协作交流。
从埃安泰国工厂竣工看中国车企加快海外建厂步伐.pptx
复现改进的L-SHADE差分进化算法求解最优化问题详解:附MATLAB源码与测试函数集,复现改进的L-SHADE差分进化算法求解最优化问题详解:MATLAB源码与测试集全攻略,复现改进的L-SHADE差分进化算法求最优化问题 对配套文献所提出的改进的L-SHADE差分进化算法求解最优化问题的的复现,提供完整MATLAB源代码和测试函数集,到手可运行,运行效果如图2所示。 代码所用测试函数集与文献相同:对CEC2014最优化测试函数集中的全部30个函数进行了测试验证,运行结果与文献一致。 ,复现; 改进的L-SHADE差分进化算法; 最优化问题求解; MATLAB源代码; 测试函数集; CEC2014最优化测试函数集,复现改进L-SHADE算法:最优化问题的MATLAB求解与验证
可选择参考电压与输出电压 可选择电阻精度以及输出电压误差值
西门子博途三部十层电梯程序案例解析:基于Wincc RT Professional V14及更高版本的应用探索,西门子博途三部十层电梯程序案例解析:基于Wincc RT Professional画面与V14及以上版本技术参考,西门子1200博途三部十层电梯程序案例,加Wincc RT Professional画面三部十层电梯程序,版本V14及以上。 程序仅限于参考资料使用。 ,西门子;1200博途;三部十层电梯程序案例;Wincc RT Professional;V14以上程序版本。,西门子V14+博途三部十层电梯程序案例:Wincc RT Pro专业画面技术解析
2023政务大数据解决方案.pptx
项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行;功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用
内容概要:本文介绍了基于Java的学业跟踪评价系统的详细设计与实现,涵盖系统的多维度数据整合与评价、智能化学习建议、数据可视化和实时反馈等方面。系统通过收集课堂表现、作业成绩、考试成绩等多源数据,对学生的学业表现进行全面跟踪和评价,提供可视化反馈以及个性化的学习建议,促进家校互动,助力学生全面素质提升和发展。 适合人群:具备一定Java编程经验的研究者和开发者,特别是从事教育信息化领域的从业人员和技术爱好者。 使用场景及目标:该系统主要用于K12教育阶段、高等教育以及其他涉及教育培训的场景。其目的是提高教育管理效率、推进教育数字化转型和个人化教育实施。 其他说明:该文档详细介绍了系统的设计思路、功能模块和技术细节,并提供了完整的程序代码以及GUI设计说明。对于希望深入了解或实际部署学业跟踪评价系统的机构非常有参考价值。文中强调技术创新与实践经验相结合,突出了实用性和前瞻性特点。
项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行;功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用
erlang安装包,rabbmit安装环境
linux 下的oracle数据库的开机启动脚本,将里面的/home/oracle/app/oracle/product/11.2.0/dbhome_1 都改成你的oracle数据库的路径。在root用户下chmod +x 添加执行权限,然后./oracle_setup.sh 执行即可。
基于目标级联分析法的多微网主动配电系统自治优化经济调度算法实现与初级应用,基于目标级联分析法的多微网主动配电系统自治优化经济调度算法实践:初级拉格朗日算法应用,GAMS代码:基于目标级联分析法的多微网主动配电系统自治优化经济调度 该代码并非完全复现该文献,而是参照文献 《基于目标级联分析法的多微网主动配电系统自治优化经济调度》 的目标级联分析法(ATC)的算法部分,采用初级的拉格朗日算法,主网与配网部分模型较为简化。 代码结构完整,注释详细,可读性较强,可以在此基础上进行修改或者移植。 适用于初学者学习ATC模型 ,GAMS代码;目标级联分析法(ATC);微网主动配电系统;自治优化经济调度;拉格朗日算法;主网与配网模型简化;代码结构完整;注释详细;可读性强;初学者学习ATC模型。,基于ATC算法的GAMS多微网经济调度优化代码:简化版学习指南
基于ISODATA改进算法的负荷场景曲线聚类——适用于风光场景生成的高效算法创新,基于ISODATA改进算法的负荷场景曲线聚类(适用于风光场景生成,包含K-means等多种聚类方法与效果评价),基于ISODATA改进算法的负荷场景曲线聚类(适用于风光场景生成) 摘要:代码主要做的是一种基于改进ISODATA算法的负荷场景曲线聚类,代码中,主要做了四种聚类算法,包括基础的K-means算法、ISODATA算法、L-ISODATA算法以及K-L-ISODATA算法,并且包含了对聚类场景以及聚类效果的评价,通过DBI的计算值综合对比评价不同方法的聚类效果,程序实现效果非常好,适合对于算法创新有需求的人,且也包含基础的k-means算法,用来学习也非常棒 另外,此代码同样适用于风光场景生成,自己准备好风光场景数据即可 代码非常精品,有部分注释; ,核心关键词: 1. 基于ISODATA改进算法 2. 负荷场景曲线聚类 3. K-means算法 4. 聚类场景评价 5. 聚类效果评价 6. DBI计算值 7. 算法创新需求 8. 风光场景生成 以上关键词用分号分隔为: 1. 基于ISO
xPack qemu arm 是一款高性能且跨平台的 ARM 架构虚拟机
莫理莉+AI+为新型能源系统赋能-技术与建筑建筑供配电论坛琶洲.pptx
学生毕业离校系统(源码+数据库+论文+ppt)java开发springboot框架javaweb,可做计算机毕业设计或课程设计 【功能需求】 本系统分为学生、教师、管理员3个角色 (1)学生功能需求 学生进入系统可以查看首页、个人中心、离校流程、网站公告、费用结算管理、论文审核管理、我的收藏管理等操作。 (2)教师功能需求 教师进入系统可以查看首页、学生管理、离校流程管理、费用结算管理、论文审核管理等操作。 (2)管理员功能需求 管理员登陆后,主要功能模块包括首页、个人中心、学生管理、教师管理、离校信息管理、费用结算管理、论文审核管理、管理员管理、留言板管理、系统管理等功能。 【环境需要】 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.数据库:MySql 5.7/8.0等版本均可; 【购买须知】 本源码项目经过严格的调试,项目已确保无误,可直接用于课程实训或毕业设计提交。里面都有配套的运行环境软件,讲解视频,部署视频教程,一应俱全,可以自己按照教程导入运行。附有论文参考,使学习者能够快速掌握系统设计和实现的核心技术。
揭秘 OpenAI 在 2027 年前创建 AGI 的计划.pptx
单极双极调制下,线路阻抗不匹配时两台单相逆变器并联的离散仿真模型研究,单极双极调制下,线路阻抗不匹配时单相逆变器Simulink并联仿真模型研究,单相逆变器Simulink并联离散仿真模型,输入电压400V,单台逆变器功率为2000W,使用下垂控制方案,在线路阻抗不匹配的情况下,实现两台逆变器并联。 可以选调制方案为单极性调制或者双极性调制。 离散模型,功率均分效果,两台逆变器输出电压和电流波形如下图。 ,核心关键词:单相逆变器; Simulink; 并联离散仿真模型; 输入电压400V; 单台功率2000W; 下垂控制方案; 线路阻抗不匹配; 调制方案; 单极性调制; 双极性调制; 功率均分效果。,离散仿真模型下,单相逆变器并联研究——400V输入、2000W功率均分实现