Mysql查询优化-DB篇
本文重点从数据库本身角度,硬件和环境的优化不在本文范围内
1. 使用索引(Index All Columns Used in 'where', 'order by', and 'group by' Clauses)
索引的作用就不用在这里说了,需要说明的是其副作用:索引会占用更多的空间,并导致增删改速度会变慢
一个很重要的问题是,如果建立索引之后,发现查询速度并没有加快,那么如果去排查呢?这就需要借助于执行计划(execution plan)了
下面是建立索引前后的执行计划:
explain SELECT title, body FROM test.articles where title ='数据库管理'
建索引前:
建立索引:ALTER TABLE articles ADD INDEX index_title (title)
建索引后:
索引是否有效,不只需要确认执行计划中的key,而且需要确认key_len
比如此处的title是varchar(200),而且表的编码为utf8mb4(兼容性好于utf8),一个字符占4个字节,key_len=200*4 + 1(标示是否NULL) + 2(长度)
索引的数据结构:
Mysql的索引使用的是B+二叉树(进一步,需要了解二叉树,平衡二叉树或者AVL树,红黑树,B/B+树)
B+树索引并不能找到一个给定键值的具体行,它找到的只是被查找数据行所在的页,接着数据库会把页读入到内存,再在内存中进行查找,最后得到要查找的数据。
**对于连接查询,只需要在关联顺序中的第二张表的相应列上创建索引即可。
**覆盖索引(包含所有需要查询的字段的值)对于字段少的查询非常有用
**应避免冗余和重复索引,参考
**不支持函数索引,但支持前缀索引(也就是对前N个字符创建索引)
**列的基数(比如数值范围)越大,索引效果越好
**尽量使用短索引
**利用最左前缀:例如 ALTER TABLE student ADD INDEX lname_birth_age (name,birthday,age); 相当于建立了三个索引:(name),(name,birthday),(name,birthday,age),所以要把常用的放在最左边
2. 用Union代替like(Optimize Like Statements With Union Clause)
如果是分别建立索引,那么作用会更大。另外,UNION ALL 要比 UNION 快很多(如果知道不重复,就应该使用Union All)
mysql> select * from students where first_name like 'Ade%' or last_name like 'Ade%' ; => mysql> select from students where first_name like 'Ade%' union all select from students where last_name like 'Ade%' ;
3. 避免在开头使用通配符(Avoid Like Expressions With Leading Wildcards)
会导致索引无法使用(比如 like '%abc')而进行全表扫描,索引就类似字典的目录,试想如果只知道词语的后半部分,又如何去查找目录呢?
解决方法:
1)对于'%xx',使用reverse函数:reverse(name) like reverse(‘%245′)
2)对于'%xx%',使用instr函数: instr(t.column,’xx’)> 0
4. 使用Mysql的全文搜索(FTS:full-text search)
使用举例:
mysql>Alter table students ADD FULLTEXT (first_name, last_name);
mysql>Select * from students where match(first_name, last_name) AGAINST ('Ade'); // 默认使用自然语言匹配单词
关于FTS,有几个需要注意的地方:
1)只在MyISAM或者InnoDB适用
2)只用于字段char,varchar,text
3)自5.7.6开始,支持CJK语言(需要使用ngram解析:ADD FULLTEXT INDEX `first_name` (`first_name` ASC, `last_name` ASC) WITH PARSER ngram;)
4)对于大量数据迁移,可以先迁移数据再创建FTS,这样比先建FTS再迁移快得多
5. 优化表结构
1)数据类型:shorter is always better. 比如如果用户量不多于100,可以用TINYINT作为ID;再如如果DateTime够用,就不要用Timestamp;数字类型不要用varchar表示
“shorter is alwasys better”同样适用于查询语句:保持查询简单且只返回必需的数据,减小通信间数据包的大小和数量是一个非常好的习惯,这也是查询中尽量避免使用SELECT *以及加上LIMIT限制的原因之一。
2)避免使用Null:如果使用,则在sum这列值的时候就需要筛选,否则就会出现错误
3)避免定义的列数太多,可以用多个小表代替一个大表,但也要注意不要过度设计
4)join时尽可能少关联表
6. 使用Mysql的缓存机制
查看是否使用缓存:show variables like 'have_query_cache';
关于缓存的参数可以在my.cnf中设置
对于缓存的命中,需要了解以下情况
1)两个查询在任何字符上的不同(例如:空格、注释),都会导致缓存不会命中。
2)如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、mysql库中的系统表,其查询结果都不会被缓存。比如函数NOW()或者CURRENT_DATE()会因为不同的查询时间,返回不同的查询结果,将这样的查询结果缓存起来没有任何的意义
3)缓存失效时机:查询对应的表数据发生变化
4)只有当缓存带来的资源节约大于其本身消耗的资源时,才会给系统带来性能提升
5)可以使用SQL_CACHE和SQL_NO_CACHE控制查询语句是否使用缓存,比如:select SQL_NO_CACHE count(*) from users where email = 'hello';
6)不要轻易打开查询缓存,特别是写密集型应用。如果你实在是忍不住,可以将query_cache_type设置为DEMAND,这时只有加入SQL_CACHE的查询才会走缓存,其他查询则不会,这样可以非常自由地控制哪些查询需要被缓存
7. 用 PreparedStatement, 一般来说比 Statement 性能高
一个 sql发给服务器去执行,涉及步骤:语法检查、语义分析, 编译,缓存
详情可查看笔者的另一篇文章:PreparedStatement是如何防止SQL注入的?
参考:https://dzone.com/articles/how-to-optimize-mysql-queries-for-speed-and-perfor
云栖:https://yq.aliyun.com/articles/697956?spm=a2c4e.11163080.searchblog.38.270f2ec1kLwArF
树结构:https://www.cnblogs.com/tiancai/p/9024351.html
重复索引:https://www.cnblogs.com/happyflyingpig/p/7663000.html
全文搜索:https://dev.mysql.com/doc/refman/5.7/en/fulltext-search.html
持续补充中...
Mysql查询优化-DB篇的更多相关文章
- 1025WHERE执行顺序以及MySQL查询优化器
转自http://blog.csdn.net/zhanyan_x/article/details/25294539 -- WHERE执行顺序-- 过滤比较多的放在前面,然后更加容易匹配,从左到右进行执 ...
- .NET C#到Java没那么难,DB篇
前言 .NET C#到Java没那么难,都是面向对象的语言,而且语法还是相似的,先对比一下开发环境,再到Servlet,再到MVC,都是一样一样的,只是JAVA的配制项比较多而已,只要配好一个,后面都 ...
- 小白两篇博客熟练操作MySQL 之 第一篇
小白两篇博客熟悉操作MySQL 之 第一篇 一.概述 1. 什么是数据库? 答: 储存数据的仓库, 如: 在ATM的事例中创建的一个db 目录, 称为数据库 2. 什么是Mysql, Oracl ...
- 小白两篇博客熟练操作MySQL 之 第二篇
小白两篇博客熟练操作MySQL 之 第二篇 一. 视图 视图是一个虚拟表,其本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用名称即可获取结果集, 并可以将其当做表来使用. s ...
- 深入了解MySQL,一篇简短的总结
MySQL的基本语法 这里作为MySQL部分模块的深入了解,大部分都是理论方面的笔记,不会写具体用法. 具体用法会记录在下面这个随笔分类下,不过暂时还没更新完,等过段时间会更新下事务.存储过程.索引等 ...
- 精通MySQL之架构篇
老刘是即将找工作的研究生,自学大数据开发,一路走来,感慨颇深,网上大数据的资料良莠不齐,于是想写一份详细的大数据开发指南.这份指南把大数据的[基础知识][框架分析][源码理解]都用自己的话描述出来,让 ...
- MYSQL(基本篇)——一篇文章带你走进MYSQL的奇妙世界
MYSQL(基本篇)--一篇文章带你走进MYSQL的奇妙世界 MYSQL算是我们程序员必不可少的一份求职工具了 无论在什么岗位,我们都可以看到应聘要求上所书写的"精通MYSQL等数据库及优化 ...
- Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析
Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析 Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析1 存 ...
- MySQL查询优化之explain的深入解析
在分析查询性能时,考虑EXPLAIN关键字同样很管用.EXPLAIN关键字一般放在SELECT查询语句的前面,用于描述MySQL如何执行查询操作.以及MySQL成功返回结果集需要执行的行数.expla ...
随机推荐
- HTML编码的用户输入------阻止向Controller的方法传入参数时用链接注入javascript代码或者HTML标记
- 记一次log4j日志文件小事故
最近散仙在做公司的一个跟搜索有关的数据分析项目,主要就是统计搜索的转化率,目的主要有以下几个: (1)通过数据分析挖掘,找出搜索业务在整个平台系统里的GMV里所占份额 (2)给公司的搜索算法调优,提供 ...
- Java基础知识(数据类型和集合)
一.数据类型 包装类型 包装类型是对基本数据类型不足之处的补充. 基本数据类型的传递方式是值传递,而包装类型是引用传递,同时提供了很多数据类型间转换的方法. Java1.5 以后可以自动装箱和拆箱 二 ...
- html的常用标签详解1
1.<!DOCTYPE html> 文档声明,不算是标签,但是它可是不能少.这玩意是干什么用的呢? 它是向浏览器自报家门的,即告诉浏览器的解析器应该以什么样的文档类型定义(DTD)来解析它 ...
- 判断django中的orm为空
result= Booking.objects.filter() #方法一 .exists() if result.exists(): print "QuerySet has Data&qu ...
- js算法之把一个数组按照指定的数组大小分割成若干个数组块
题目描述: 把一个数组arr按照指定的数组大小size分割成若干个数组块. 例如: chunk([1,2,3,4],2)=[[1,2],[3,4]]; chunk([1,2,3,4,5 ...
- 19-10-18-Y
ZJ一下: 感觉能拿到的分都拿到了,至于后来改题就缶了 其实是:太tui导致没改好 TJ: T1: 正解是$\mathsf{KMP}$,但是广大群众都用了$\mathsf{hash}$…… 发现了一个 ...
- 机器学习中的隐马尔科夫模型(HMM)详解
机器学习中的隐马尔科夫模型(HMM)详解 在之前介绍贝叶斯网络的博文中,我们已经讨论过概率图模型(PGM)的概念了.Russell等在文献[1]中指出:"在统计学中,图模型这个术语指包含贝叶 ...
- Java通过接口或者抽象类调用方法的时候,怎么知道调用的是哪个实现类里的方法?
用对象的 getClass() 方法获得它的类,之后就可以随意去判断这是哪个实现类了. 比如代码1-1所示的JDBC连接池的代码,我们想要知道conn调用的close方法是释放连接还是归还连接, 我们 ...
- Jmeter分布式测试过程中遇到的问题及摘抄前辈问题汇总
遇到的常见问题: 1.在Controller端上控制某台机器Run,提示"Bad call to remote host". 解决方法:检查被控制机器上的jmeter-server ...