数据库设计与优化 - 结合执行计划MySQL语句的11大优化策略
背景
全球访问量最大的 20 家网站,绝大多数使用 MySQL,有两个特例的 live.com 和 bing 是微软旗下的网站。它使用的是 MSSQL,并不是他们使用不了 MySQL,而是他要支持自己的数据库。毫无疑问MySQL是当今非常流行的关系数据库之一,不仅因为其绝大多数版本的开源,而且支持多存储引擎、快速、稳定地运行于各种服务器环境。MySQL查询分析优化引擎作为其中核心模块的一部分,占有举足轻重的地位,因此我们今天了解和研究它就非常重要了。
MySQL服务器操作层架构
MySQL语句的优化就发生MySQL Server服务器架构的操作层,这层具体的执行流程是:
这层主要的功能是: SQL 语句的解析、优化,缓存的查询,MySQL 内置函数的实现,跨存储引擎功能(所谓跨存储引擎就是说每个引擎都需提供的功能(引擎需对外提供接口)),例如:存储过程、触发器、视图等。
1.如果是查询语句(select 语句),首先会查询缓存是否已有相应结果,有则返回结果,无则进行下一步(如果不是查询语句,同样调到下一步);
2.解析查询,创建一个内部数据结构(解析树),这个解析树主要用来 SQL 语句的语义与语法解析;
3.优化:优化 SQL 语句,例如重写查询,决定表的读取顺序,以及选择需要的索引等。这一阶段用户是可以查询的,查询服务器优化器是如何进行优化的,便于用户重构查询和修改相关配置,达到最优化。这一阶段还涉及到存储引擎,优化器会询问存储引擎,比如某个操作的开销信息、是否对特定索引有查询优化等。
十一大优化策略
演示准备
用以上演示道具来说明十一经典优化策略如下:
策略一、索引字段尽量全值匹配
-- 查询1
EXPLAIN SELECT * FROM employee WHERE `name`='joye'; -- 走索引
-- 查询2
EXPLAIN SELECT * FROM employee WHERE `name`='joye' AND age=25; -- 走索引
-- 查询3
EXPLAIN SELECT * FROM employee WHERE `NAME`='joye' AND age=25 AND pos='dev'; -- 走索引
以上三种查询方式,查询3的效率最高,索引的使用程度也最高。在表中建立索引后,能用索引的要尽量都要用上。
策略二、最佳左前缀法则
如果创建的索引为复合索引,要遵守最左前缀法则。查询从索引的最左前列开始并且不要跳过索引中的列。
-- 查询1
EXPLAIN SELECT * FROM employee WHERE age=20 AND pos='dev'; -- 不走索引
-- 查询2
EXPLAIN SELECT * FROM employee WHERE pos='dev'; -- 不走索引
-- 查询3
EXPLAIN SELECT * FROM employee WHERE `name`='Joye'; -- 走索引
以上查询只有查询3才走索引。最佳左前缀法则可以理解成火车的车头、中间车厢、车尾的关系。
策略三、不在索引列上做任何操作
在索引列上计算、函数、类型转换等会导致索引失效,转向全表扫描。
-- 查询1
EXPLAIN SELECT * FROM employee WHERE `name`='Joye'; -- 走索引
-- 查询2
EXPLAIN SELECT * FROM employee WHERE LEFT(`name`,4)='Joye'; -- 不走索引
-- 查询3
EXPLAIN SELECT * FROM employee WHERE `age`*2 = 13; -- 不走索引
在索引字段上使用函数、任何计算表达式均会导致索引失效。
策略四、尽量多用覆盖索引
尽量使用覆盖索引(只访问索引列的查询,查询列和索引列一致),减少select开销。全部数据直接通过索引就能获取到,大大提高查询效率。
-- 查询1
EXPLAIN SELECT age,pos FROM employee WHERE `name` = 'joye'; -- 走索引
-- 查询2
EXPLAIN SELECT pos FROM employee WHERE `name` = 'joye'; -- 走索引
-- 查询3
EXPLAIN SELECT age,add_time FROM employee WHERE `name` = 'joye'; -- 不走索引
策略五、范围条件放最后
查询优化器不会使用索引中范围条件右边的列,所以范围条件放最后能被主动采用。
-- 查询1
EXPLAIN SELECT * FROM employee WHERE `NAME`='joye' AND age=22 AND pos='manager'; -- 走索引
-- 查询2
EXPLAIN SELECT * FROM employee WHERE `NAME`='joye' AND age>22 AND pos='manager';-- 不充分走索引
-- 查询3
EXPLAIN SELECT * FROM employee WHERE `NAME`='joye' AND pos='manager' AND age>22; -- 充分走索引
策略六、不等于(! <>) 要慎用
mysql在使用不等于(!= 或者 <>)的时候无法使用索引,导致全表扫描
-- 查询1
EXPLAIN SELECT * FROM employee WHERE `name` != 'joye'; -- 不走索引
-- 查询2
EXPLAIN SELECT * FROM employee WHERE NAME <>'joye'; -- 不走索引
若要使用不等号,尽量采用覆盖索引;
-- 查询3
EXPLAIN SELECT `name`,age,pos FROM employee WHERE NAME != 'joye'; -- 走索引
-- 查询4
EXPLAIN SELECT NAME,age,pos FROM employee WHERE NAME <> 'joye'; -- 走索引
策略七、IN/NOT IN要慎用
-- 查询1
EXPLAIN SELECT * FROM employee WHERE `name` IN('joye','9000'); -- 不走索引
-- 查询2
EXPLAIN SELECT * FROM employee WHERE `name` NOT IN('joye','9000'); -- 不走索引
查询1和查询2不走索引的原因是IN/NOT IN 匹配让索引失效,转向全表扫描 。若需要使用IN/NOT IN,则同时尽量采用覆盖索引或就使用场景使用JOIN连表方式
-- 查询3
EXPLAIN SELECT age,pos FROM employee WHERE `name` IN('joye','9000'); -- 走索引
-- 查询4
EXPLAIN SELECT age,pos FROM employee WHERE `name` NOT IN('joye','9000'); -- 充分使用索引
策略八、NULL/NOT NULL有影响
索引字段为null 和 not null 对索引的影响, 可能导致索引失效(分情况)。
-- 查询1
EXPLAIN SELECT * FROM employee WHERE `name` IS NULL; -- 不走索引
-- 查询2
EXPLAIN SELECT * FROM employee WHERE `name` IS NOT NULL; -- 不走索引
这时设置`name`字段允许为null
-- 查询3
EXPLAIN SELECT * FROM employee2 WHERE NAME IS NULL; -- 走索引
策略九、LIKE查询要小心
LIKE以通配符开头(‘%abc ’)mysql索引失效会变成全表扫描操作。
-- 查询1
EXPLAIN SELECT * FROM employee WHERE `name` LIKE '%july%' -- 不走索引
-- 查询2
EXPLAIN SELECT * FROM employee WHERE `name` LIKE '%july' -- 不走索引
-- 查询3
EXPLAIN SELECT * FROM employee WHERE `name` LIKE 'july%'-- 走索引
策略十、字符类型字段加引号
字符窜不加引号会导致索引失效。
-- 查询1
EXPLAIN SELECT * FROM employee WHERE `name` = 9000; -- 不走索引
-- 查询2
EXPLAIN SELECT * FROM employee WHERE `name` = '9000' -- 走索引
策略十一、OR改UNION 效率高
WHERE查询或子查询条件中使用OR,会导致索引失效,转向全表数据扫描。
-- 查询1
EXPLAIN SELECT * FROM employee WHERE `name`='joye' OR `name`='andy3'; -- 不走索引
-- 查询2
EXPLAIN
SELECT * FROM employee WHERE `name`='joye'
UNION
SELECT * FROM employee WHERE `name`='andy3'; -- 走索引
总结
以上仅为SQL语句优化领域的关键优化指标和技巧。在具体项目的优化中,我们可能会综合使用以上多个策略和手段完成一个SQL的优化;如何用好这些策略完全取决于我们在项目实战中循序渐进的优化、尝试、摸索、总结。以后会在项目实践中,分享更多综合性大数据问题优化实战案例,请继续关注!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
新Jenkins实践-第1章 开篇-为什么要做CI/CD?
本章阐述持续集成系统的发展历程、持续集成系统的原理,以及持续集成系统的实现过程,目的是让大家全面了解持续集成系统,更加深入的学习持续集成系统的原理,为后续章节的学习做好准备。我会分享一些个人的经验。 1.1 传统的应用发布模式 如果你没有亲身体验过传统的应用发布,你可能不会觉得CI/CD有什么吸引人的地方。一般一个开发团队中都会存在多个角色:开发、测试、运维。 当时我们的应用发布模式可以能是这样的: 开发同学进行项目代码开发,本地运行测试成功后将代码上传到版本控制系统。 开发同学通知运维同学项目可以发布了,然后运维同学下载代码进行打包和构建,生成应用制品。 运维同学使用部署脚本将生成的制品部署到测试环境,并提示测试同学可以进行产品的测试。 测试同学开始进行手动、自动化测试,测试完成后提醒运维同学可以进行预生产环境部署。 运维同学开始进行预生产环境部署,然后测试同学进行测试,测试完成后,开始部署生产环境。 当然我描述的可能只是其中的一部分,手动操作很多、出现的问题很多。上面看似很流畅的过程,其实每次构建或发布都可能会出现问题。未对每次提交验证、构建环境不一致:开发人员本地测试成功后提交代...
- 下一篇
Databricks数据洞察应用场景有哪些?
云栖号快速入门:【点击查看更多云产品快速入门】不知道怎么入门?这里分分钟解决新手入门等基础问题,可快速完成产品配置操作! Databricks数据洞察(简称DDI)的核心引擎是Databricks Runtime和Databricks Delta Lake。商业版引擎的加持下,为您提供了新一代云数仓的解决方案。本文为您介绍Databricks数据洞察适用的典型应用场景。 数据湖分析 Databricks数据洞察支持计算存储分离的数据湖架构。 使用阿里云对象存储OSS作为云上存储,DDI集群提供灵活的计算资源,OSS上的数据可以被多个DDI集群共享,减少数据冗余。同时,DataInsight Notebook支持多用户同时协同工作,您可以在Notebook中完成作业编辑、提交和结果查看。 实时数仓 利用Databricks Delta Lake的ACID事务特性,可以构建云上大数据的实时数仓。 本文来自 阿里云文档中心 Databricks数据洞察 应用场景 【云栖号在线课堂】每天都有产品技术专家分享!课程地址:https://yqh.aliyun.com/zhibo 立即加入社群,与专...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- Red5直播服务器,属于Java语言的直播服务器
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Windows10,CentOS7,CentOS8安装Nodejs环境