查询缓存及索引:MySQL系列之九
一、MySQL的架构
- 连接器
- 连接池,安全认证、线程池、连接限制、检查内存、缓存
- SQL接口 DML、DDL
- SQL解析器,对SQL语句的权限检查、解析为二进制程序
- 优化器,优化访问路径
- 缓存cache,buffer
- 存储引擎 innodb
- 文件系统
- 日志
二、查询缓存(Query Cache)
SQL语句
查询缓存
解析器
解析树
预处理
查找最好的查询路径
查询优化SQL语句
执行计划
API调用存储引擎
调用数据,返回结果
缓存SELECT操作或预处理查询的结果集和SQL语句,当有新的SELECT语句或预处理查询语句请求,先去查询缓存,判断是否存在可用的记录集,判断标准:与缓存的SQL语句,是否完全一样,区分大小写。
不需要对SQL语句做任何解析和执行,当然语法解析必须通过在先,直接从Query Cache中获得查询结果,提高查询性能
查询缓存的判断规则,不够智能,也即提高了查询缓存的使用门槛,降低其效率;查询缓存的使用,会增加检查和清理Query Cache中记录集的开销
哪些查询可能不会被缓存:
- 查询语句中加了SQL_NO_CACHE参数;
- 查询语句中含有获得值的函数,包含自定义函数,如:NOW()、CURDATE()、GET_LOCK()、RAND()、CONVERT_TZ()等;
- 对系统数据库的查询:mysql、information_schema 查询语句中使用SESSION级别变量或存储过程中的局部变量;
- 查询语句中使用了LOCK IN SHARE MODE、FOR UPDATE的语句,查询语句中类似SELECT …INTO 导出数据的语句;
- 对临时表的查询操作;存在警告信息的查询语句;不涉及任何表或视图的查询语句;某用户只有列级别权限的查询语句;
- 事务隔离级别为Serializable时,所有查询语句都不能缓存。
查询缓存相关的服务器变量:
- query_cache_min_res_unit: 查询缓存中内存块的最小分配单位,默认4k,较小值会减少浪费,但会导致更频繁的内存分配操作,较大值会带来浪费,会导致碎片过多,内存不足;
- query_cache_limit:单个查询结果能缓存的最大值,默认为1M,对于查询结果过大而无法缓存的语句,建议使用SQL_NO_CACHE;
- query_cache_size:查询缓存总共可用的内存空间;单位字节,必须是1024的整数倍,最小值40KB,低于此值有警报;
- query_cache_wlock_invalidate:如果某表被其它的会话锁定,是否仍然可以从查询缓存中返回结果,默认值为OFF,表示可以在表被其它会话锁定的场景中继续从缓存返回数据;ON则表示不允许;
- query_cache_type: 是否开启缓存功能,取值为ON, OFF, DEMAND,默认值为ON
- 值为OFF或0时,查询缓存功能关闭;
- 值为ON或1时,查询缓存功能打开,SELECT的结果符合缓存条件即会缓存,否则,不予缓存,显式指定SQL_NO_CACHE,不予缓存;
- 值为DEMAND或2时,查询缓存功能按需进行,显式指定SQL_CACHE的SELECT语句才会缓存;其它均不予缓存。
MariaDB [(none)]> SHOW VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name | Value |
+------------------------------+----------+
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 33554432 |
| query_cache_strip_comments | OFF |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
+------------------------------+----------+
优化查询缓存:
查询缓存相关的状态变量:
- Qcache_free_blocks:处于空闲状态 Query Cache中内存 Block 数;
- Qcache_free_memory:处于空闲状态的 Query Cache 内存总量;
- Qcache_hits:Query Cache 命中次数;
- Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次数,即没有命中的次数;
- Qcache_lowmem_prunes:当 Query Cache 内存容量不够,需要删除老的Query Cache 以给新的 Cache 对象使用的次数;
- Qcache_not_cached:没有被 Cache 的 SQL 数,包括无法被 Cache 的 SQL 以及由于 query_cache_type 设置的不会被 Cache 的 SQL语句;
- Qcache_queries_in_cache:在 Query Cache 中的 SQL 数量;
- Qcache_total_blocks:Query Cache 中总的 Block。
MariaDB [(none)]> SHOW GLOBAL STATUS LIKE 'Qcache%';
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 33536824 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 4 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+----------+
命中率和内存使用率估算:
- 查询缓存中内存块的最小分配单位query_cache_min_res_unit :(query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache
- 查询缓存命中率 :Qcache_hits / ( Qcache_hits + Qcache_inserts ) * 100%
- 查询缓存内存使用率:(query_cache_size – qcache_free_memory) / query_cache_size * 100%
三、索引
索引是特殊数据结构:定义在查找时作为查找条件的字段,索引实现在存储引擎。
- 索引可以降低服务需要扫描的数据量,减少了IO次数
- 索引可以帮助服务器避免排序和使用临时表
- 索引可以帮助将随机I/O转为顺序I/O
- 但是占用额外空间,影响插入速度
1、索引类型:
B + Tree 索引:顺序存储,每一个叶子节点到根的距离都是相同的,左前缀索引,适合查询范围类的数据;
- 适合使用B-Tree索引的查询类型
- 全值匹配
- 匹配最左前缀
- 匹配范围值
- 精确匹配某一列并范围匹配另一列(复合索引)
- 只访问索引的查询
- 不适合使用B-tree索引的查询类型
- 不从最左列开始
- 不能跳过索引中的列
- 如果查询中某个列是为范围查询那么右侧的列无法再使用索引优化查询Hash索引:基于哈希表,构建出键值对的索引,特别适用于精确匹配索引中的索引列,只支持等值比较查询(IN,=,<>);不适合于顺序查询,不支持模糊匹配;只有Memory存储引擎支持显式Hash索引
空间索引(R - Tree):只有MyISAM支持空间索引
全文索引(FULL TEXT):在文本中查找关键词
2、高性能索引策略:
- 独立使用列,尽量避免其参与运算
- 使用左前缀索引:索引构建于字段的左侧的多少字符要通过索引选择性来评估;索引选择性:不重复的索引值和数据表的记录总数的比值
- 多列索引:AND操作时更适合使用多列索引,而非为每个列创建单独的索引
- 选择合适的索引列次序:无排序和分组时,将选择性最高放左侧
3、索引的优化建议
- 只要列中含有NULL值,就最好不要在此例设置索引,复合索引如果有NULL值,此列在使用时也不会使用索引
- 尽量使用短索引,如果可以,应该制定一个前缀长度
- 对于经常在where子句使用的列,最好设置索引
- 对于有多个列where或者order by子句,应该建立复合索引
- 对于like语句,以%或者‘-’开头的不会使用索引,以%结尾会使用索引
- 尽量不要在列上进行运算(函数操作和表达式操作)
- 尽量不要使用not in和<>操作
- 多表连接时,尽量小表驱动大表,即小表 join 大表
- 在千万级分页时使用limit
- 对于经常使用的查询,可以开启缓存
- 大部分情况连接效率远大于子查询
4、索引的创建与删除
- 创建索引
CREATE INDEX index_name ON tbl_name (index_col_name,...);
MariaDB [hellodb]> CREATE INDEX index_name ON students(name); #创建简单索引
MariaDB [hellodb]> CREATE INDEX index_name_age ON students(name,age); #创建复合索引
- 查看索引
SHOW INDEXES FROM [db_name.]tbl_name;
MariaDB [hellodb]> SHOW INDEX FROM students\G
- 删除索引
DROP INDEX index_name ON tbl_name;
MariaDB [hellodb]> DROP INDEX index_name ON students;
- 优化表空间
MariaDB [hellodb]> OPTIMIZE TABLE students;
- 查看索引使用的情况
启用记录索引使用情况:SET GLOBAL userstat=1;
查看索引使用情况:SHOW INDEX_STATISTICS;
我们可以统计不经常使用的索引从而进行优化
四、EXPLAIN命令
通过EXPLAIN来分析索引的有效性:EXPLAIN SELECT clause
,获取查询执行计划信息,用来查看查询优化器如何执行查询
MariaDB [hellodb]> EXPLAIN SELECT name FROM students WHERE name = 'Lin Daiyu'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: students
type: ref
possible_keys: index_name_age
key: index_name_age
key_len: 152
ref: const
rows: 1
Extra: Using where; Using index
- id:当前查询语句中,每个SELECT语句的编号;复杂类型的查询有三种:简单子查询、用于FROM子句中的子查询、联合查询(UNION,注意:UNION查询的分析结果会出现一个额外匿名临时表)
- select_type:
- SIMPLE :简单查询
- SUBQUERY: 简单子查询
- PRIMARY:最外面的SELECT
- DERIVED: 用于FROM中的子查询
- UNION:UNION语句的第一个之后的SELECT语句
- UNION RESULT: 匿名临时表 - table:SELECT语句关联到的表
- type:关联类型或访问类型,即MySQL决定的如何去查询表中的行的方式,以下顺序,性能从低到高
- ALL: 全表扫描
- index:根据索引的次序进行全表扫描;如果在Extra列出现“Using index”表示了使用覆盖索引,而非全表扫描
- range:有范围限制的根据索引实现范围扫描;扫描位置始于索引中的某一点,结束于另一点
- ref: 根据索引返回表中匹配某单个值的所有行
- eq_ref:仅返回一个行,但与需要额外与某个参考值做比较
- const, system: 直接返回单个行 - possible_keys:查询可能会用到的索引
- key: 查询中使用到的索引
- key_len: 在索引使用的字节数
- ref: 在利用key字段所表示的索引完成查询时所用的列或某常量值
- rows:MySQL估计为找所有的目标行而需要读取的行数
- Extra:额外信息
- Using index:MySQL将会使用覆盖索引,以避免访问表
- Using where:MySQL服务器将在存储引擎检索后,再进行一次过滤
- Using temporary:MySQL对结果排序时会使用临时表
- Using filesort:对结果使用一个外部索引排序
五、SQL语句性能优化
- 查询时,能不要*就不用*,尽量写全字段名
- 大部分情况连接效率远大于子查询
- 多表连接时,尽量小表驱动大表,即小表 join 大表
- 在千万级分页时使用limit
- 对于经常使用的查询,可以开启缓存
- 多使用explain和profile分析查询语句
- 查看慢查询日志,找出执行时间长的sql语句优化
查询缓存及索引:MySQL系列之九的更多相关文章
- mysql 慢查询,查询缓存,索引,备份,水平分割
1.开启慢查询 在mysql的配置文件my.ini最后增加如下命令 [mysqld]port=3306slow_query_log =1long_query_time = 1 2.查看慢查询记录 默认 ...
- MySQL查询缓存设置提高MySQL查询性能
首先看看MSYQL逻辑框架:图片来自高性能mysql 如果使用了QueryCache,当查询接收到一个和之前同样的查询,服务器将会从查询缓存中检索结果,而不是再次分析和执行相同的查询.这样就能大大提高 ...
- MySQL 查询缓存机制(MySQL数据库调优)
查询缓存机制:缓存的是查询语句的整个查询结果,是一个完整的select语句的缓存结果 哪些查询可能不会被缓存 :查询中包含UDF.存储函数.用户自定义变量.临时表.mysql库中系统表.或者包含列级别 ...
- Mysql系列(九)—— 性能分析explain执行计划
explain是mysql中sql优化的一个重要手段.顾名思义,explain就是解释sql,用于表示sql是怎样执行的信息,即sql执行计划! 语法 explain statement statem ...
- Oracle索引梳理系列(九)- 浅谈聚簇因子对索引使用的影响及优化方法
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...
- mysql 开发进阶篇系列 23 应用层优化与查询缓存
一.概述 前面章节介绍了很多数据库的优化措施,但在实际生产环境中,由于数据库服务器本身的性能局限,就必须要对前台的应用来进行优化,使得前台访问数据库的压力能够减到最小. 1. 使用连接池 对于访问数据 ...
- mysql基础之-mysql查询缓存(九)
0x01 MySQL查询缓存 用于保存MySQL查询语句返回的完整结果,被命中时,MySQL会立即返回结果,省去解析.优化和执行等操作 如何检查缓存?? MySQL保存结果与缓存中: 把select语 ...
- 生产要不要开启MySQL查询缓存
一.前言 在当今的各种系统中,缓存是对系统性能优化的重要手段.MySQL Query Cache(MySQL查询缓存)在MySQL Server中是默认打开的,但是网上各种资料以及有经验的DBA都建议 ...
- MySQL的万字总结(缓存,索引,Explain,事务,redo日志等)
hello,小伙伴们,好久不见,MySQL系列停更了差不多两个月了,也有小伙伴问我为啥不更了呢?其实我去看了MySQL的全集,准备憋个大招,更新篇长文(我不会告诉你是因为我懒的). 好了,话不多说,直 ...
随机推荐
- 洛谷 2822 组合数问题——质因数有关的dp
题目:https://www.luogu.org/problemnew/show/P2822 发现 k 都是一样的.所以可以设dp[ i ][ j ]表示 n<=i,m<=j 的答案.发现 ...
- Centos下Yum安装PHP5.5
默认的版本太低了,手动安装有一些麻烦,想采用Yum安装的可以使用下面的方案: 1.检查当前安装的PHP包 yum list installed | grep php 如果有安装的PHP包,先删除他们 ...
- python中文件打开的各个标识含义
w代表清空后写入 r代表打开后追查 +代表可以写 b代表二进制写入
- 【转】Jquery折叠效果
转自:http://www.cnblogs.com/clc2008/archive/2011/10/25/2223254.html <!DOCTYPE html PUBLIC "-// ...
- js浮点数运算出现误差解决方案
1.数据展示类(使用 toPrecision 凑整并 parseFloat 转成数字后再显示) parseFloat(1.4000000000000001.toPrecision(12)) === 1 ...
- cdh ntpdate 问题
ntpdc -np 一个正常一个不正常
- position应用之相对父元素的定位
分别添加以下style即可: 父元素position:relative; 子元素position:absolute; right:0px; bottom:0px;
- hibernate hql 查询指定…
以数组的形式抛出,前台页面就要把它当成一个数组来处理 以对象抛出,就要当成一个对象来处理. 在JSP页面使用标签时一定要注意这点. 版权声明:本文为博主原创文章,未经博主允许不得转载.
- neon eclipse tomcat发布项目乱码
解决方法如图
- 21. Bypass D盾_防火墙(旧版 and 新版)SQL注入防御(多姿势)
D盾旧版: 00前言 D盾_IIS防火墙,目前只支持Win2003服务器,前阵子看见官方博客说D盾新版将近期推出,相信功能会更强大,这边分享一下之前的SQL注入防御的测试情况.D盾_IIS防火墙注入防 ...