由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里

前几天进行了一个数据库查询,比较缓慢,便查询了一下,在这里记录一下,方便以后翻阅,

1)先复习一下查询索引

(Tue Jun  :: ) db_1 >>show keys from xxxx; ==>(与show index from xxxx  是一样的)
+--------------+------------+-------------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------+------------+-------------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| xxxx | | PRIMARY | | iId | A | | NULL | NULL | | BTREE | | |
| xxxx | | index_dPayTime | | dPayTime | A | | NULL | NULL | | BTREE | | |
| xxxx | | index_sUserName | | sUserName | A | | NULL | NULL | | BTREE | | |
| xxxx | | index_sPlatName | | iProxyId | A | | NULL | NULL | | BTREE | | |
| xxxx | | index_sPlatName | | iServerId | A | | NULL | NULL | | BTREE | | |
| xxxx | | index_sPlatName | | id | A | | NULL | NULL | YES | BTREE | | |
| xxxx | | index_dPayDate | | dPayDate | A | | NULL | NULL | | BTREE | | |
| xxxx | | Index_iPlatServerId_iPlayerId | | iPlatServerId | A | | NULL | NULL | | BTREE | | |
| xxxx | | Index_iPlatServerId_iPlayerId | | iPlayerId | A | | NULL | NULL | | BTREE | | |
| xxxx | | index_dPayDate_yue_iProxyId | | dPayDate_yue | A | | NULL | NULL | | BTREE | | |
| xxxx | | index_dPayDate_yue_iProxyId | | iProxyId | A | | NULL | NULL | | BTREE | | |
| xxxx | | index_dPayDate_yue_iProxyId | | iPayType | A | | NULL | NULL | YES | BTREE | | |

类型介绍:

1、Table 表的名称。
2、 Non_unique 如果索引不能包括重复词,则为0,如果可以则为1。
3、 Key_name 索引的名称
4、 Seq_in_index 索引中的列序列号,从1开始。
5、 Column_name 列名称。
6、 Collation 列以什么方式存储在索引中。在mysql中,有值‘A’(升序)或NULL(无分类)。
7、Cardinality 索引中唯一值的数目的估计值。通过运行ANALYZE TABLE或myisamchk -a可以更新。基数根据被存储为整数的统计数据来计数,所以即使对于小型表,该值也没有必要是精确的。基数越大,当进行联合时,MySQL使用该索引的机会就越大。
8、Sub_part 如果列只是被部分地编入索引,则为被编入索引的字符的数目。如果整列被编入索引,则为NULL。
9、 Packed 指示关键字如何被压缩。如果没有被压缩,则为NULL。
10、 Null 如果列含有NULL,则含有YES。如果没有,则该列含有NO。
11、 Index_type 用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)。
12、 Comment 索引注释

我们要注意:

 cardinality 的值越大,那么命中此索引的几率越高
我们可以强制进行命中哪个索引
Cardinality是一个预估值,而不是一个准确值,基本上用户也不可能得到一个准确的值,在实际应用中,Cardinality/n_row_in_table应尽可能的接近1,
如果非常小,那用户需要考虑是否还有必要创建这个索引。故在访问高选择性属性的字段并从表中取出很少一部分数据时,对于字段添加B+树索引是非常有必要的

如果要查看Cardinality更为详细的信息,可以在:http://www.cnblogs.com/olinux/p/5140615.html 中查看

2 ) 同事在线上进行了一次查询操作:

select * from t_xxxx where pay_id in (
select pay_id from t_xxxx where dPayTime>="2017-06-21 12:12:31" AND dPayTime<="2017-06-28 12:12:31" group by pay_id having count(pay_id) > )
  and dPayTime>="2017-06-21 12:12:31" AND dPayTime<="2017-06-28 12:12:31"

然后执行半天都出不来结果,问我这边怎么了,我看了一下:

explain select * from t_xxxx where pay_id in (
select pay_id from t_xxxx where dPayTime>="2017-06-21 12:12:31" AND dPayTime<="2017-06-28 12:12:31" group by pay_id having count(pay_id) > )

得到结果:

| id | select_type        | table        | type  | possible_keys  | key            | key_len | ref  | rows    | Extra                                        |
+----+--------------------+--------------+-------+----------------+----------------+---------+------+---------+----------------------------------------------+
| | PRIMARY | t_xxxx | ALL | NULL | NULL | NULL | NULL | | Using where |
| | DEPENDENT SUBQUERY | t_xxx | range | index_dPayTime | index_dPayTime | | NULL | | Using where; Using temporary; Using filesort |

这条sql包含了子查询和父查询,如果我们先查子查询,可以看到执行非常快:

select pay_id from t_xxxx where dPayTime>="2017-06-21 12:12:31" AND dPayTime<="2017-06-28 12:12:31" group by pay_id having count(pay_id) > ;
Empty set (0.42 sec)
0.42秒执行完毕

explain可以看到:

+----+-------------+--------------+-------+----------------+----------------+---------+------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+-------+----------------+----------------+---------+------+--------+----------------------------------------------+
| | SIMPLE | t_xxxx | range | index_dPayTime | index_dPayTime | | NULL | | Using where; Using temporary; Using filesort |
+----+-------------+--------------+-------+----------------+----------------+---------+------+--------+----------------------------------------------+

然后我们再尝试父查询查询,替换一下子查询,直接给出子查询的结果:

select * from t_xxxx where pay_id in (
-> '','','');
3 rows in set (0.50 sec)
0.56 秒查询完毕

那么两者结合起来,岂不是只需要1秒钟就可以结束查询。

然而真实情况并非如此,这不是简单的1+1,而是乘法,如果用in去操作,子查询影响的行数是多少条,就会乘以父查询影响的行数。这样的乘积量是非常大的,所以查询非常的久。

因此这里推荐改成联表==>

select * from t_xxxx tpp1, (select pay_id from t_xxxx where dPayTime>="2017-06-21 12:12:31" AND dPayTime<="2017-06-28 12:12:31" group by pay_id 
having count(pay_id) > ) tpp2
where tpp1.pay_id=tpp2.pay_id and dPayTime>="2017-06-21 12:12:31" AND dPayTime<="2017-06-28 12:12:31"

如果是联表,那么就会控制两者计算好后,才开始进行联表。而其中子查询的结果是很少的,只有几条,联表起来因此计算很快,2秒完成

这里我们也要注意,如果查询的时间跨度很大,条数很大,那么索引就不会被命中,会自动采用普通查询。

explain select * from t_xxxx tpp1, (select pay_id from t_xxxx where dPayTime>="2017-06-01 12:12:31" AND dPayTime<="2017-06-28 12:12:31" group by pay_id having 
count(pay_id) > ) tpp2 where tpp1.pay_id=tpp2.pay_id and dPayTime>="2017-06-01 12:12:31" AND dPayTime<="2017-06-28 12:12:31"
+----+-------------+--------------+--------+----------------+------+---------+------+---------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+--------+----------------+------+---------+------+---------+----------------------------------------------+
| | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | | |
| | PRIMARY | tpp1 | ALL | index_dPayTime | NULL | NULL | NULL | | Using where |
| | DERIVED | t_xxxx | ALL | index_dPayTime | NULL | NULL | NULL | | Using where; Using temporary; Using filesort |
+----+-------------+--------------+--------+----------------+------+---------+------+---------+----------------------------------------------+
并没有命中索引

那么我们就要尽量的去优化它,没有命中索引下查询起来是比较慢的。

一次mysql调优过程的更多相关文章

  1. MySQL 调优/优化的 100 个建议

    MySQL 调优/优化的 100 个建议   MySQL是一个强大的开源数据库.随着MySQL上的应用越来越多,MySQL逐渐遇到了瓶颈.这里提供 101 条优化 MySQL 的建议.有些技巧适合特定 ...

  2. MySQL调优系列基础篇

    前言 有一段时间没有写博客了,整天都在忙,上班,录制课程,恰巧最近一段时间比较清闲,打算弄弄MYSQL数据库. 关于MySQL数据库,这里就不做过多的介绍,开源.免费等特性深受各个互联网行业喜爱,尤其 ...

  3. mysql调优 基础

    MySQL调优可以从几个方面来做: 1. 架构层:做从库,实现读写分离: 2.系统层次:增加内存:给磁盘做raid0或者raid5以增加磁盘的读写速度:可以重新挂载磁盘,并加上noatime参数,这样 ...

  4. MySQL调优三步曲(慢查询、explain profile)

    在做性能测试中经常会遇到一些sql的问题,其实做性能测试这几年遇到问题最多还是数据库这块,要么就是IO高要么就是cpu高,所以对数据的优化在性能测试过程中占据着很重要的地方,下面我就介绍一些msyql ...

  5. MySQL(调优慢查询、explain profile) 转

    转自http://www.linuxidc.com/Linux/2012-09/70459.htm mysql profile explain slow_query_log分析优化查询 在做性能测试中 ...

  6. 数据库MySQL调优实战经验总结<转>

    数据库MySQL调优实战经验总结 MySQL 数据库的使用是非常的广泛,稳定性和安全性也非常好,经历了无数大小公司的验证.仅能够安装使用是远远不够的,MySQL 在使用中需要进行不断的调整参数或优化设 ...

  7. MySQL 调优基础(一) CPU与进程

    一般而言,MySQL 的调优可以分为两个层面,一个是在MySQL层面上进行的调优,比如SQL改写,索引的添加,MySQL各种参数的配置:另一个层面是从操作系统的层面和硬件的层面来进行调优.操作系统的层 ...

  8. 记一次数据库调优过程(IIS发过来SQLSERVER 的FETCH API_CURSOR语句是神马?)

    记一次数据库调优过程(IIS发过来SQLSERVER 的FETCH API_CURSOR语句是神马?) 前几天帮客户优化一个数据库,那个数据库的大小是6G 这麽小的数据库按道理不会有太大的性能问题的, ...

  9. mysql调优最大连接数

    一.mysql调优 1.1 报错: Mysql: error 1040: Too many connections 1.2 原因: 1.访问量过高,MySQL服务器抗不住,这个时候就要考虑增加从服务器 ...

随机推荐

  1. VUE项目 - IE报vuex requires a Promise polyfill in this browser问题解决

    第一步: 安装 babel-polyfill . babel-polyfill可以模拟ES6使用的环境,可以使用ES6的所有新方法 npm install --save babel-polyfill ...

  2. awk使用

    [awk使用] 例:awk -F ':' '{print $1"\t"$7}' 参考:http://www.cnblogs.com/ggjucheng/archive/2013/0 ...

  3. shell中的字符串操作和数学运算

    字符串操作   变量赋值: 说明:变量值可以用单引号.双引号.或者不加任何引号来赋值给变量 变量名="变量值" 变量名='变量值' 变量名=变量值 例如:str="hel ...

  4. 44. Wildcard Matching (String; DP, Back-Track)

    Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. ...

  5. C# Action

    Action<T> Delegate Encapsulates a method that has a single parameter and does not return a val ...

  6. ios Https问题

    HTTPS认证过程:   ① 浏览器发送一个连接请求给安全服务器.   ② 服务器将自己的证书,以及同证书相关的信息发送给客户浏览器.   ③ 客户浏览器检查服务器送过来的证书是否是由自己信赖的 CA ...

  7. 第2章—Java内存区域与内存溢出异常

    2.1 概述 总结:本章将从概念上介绍 Java 虚拟机内存的各个区域,讲解这些区域的作用.服务对象以及其中可能产生的问题. 2.2 运行时数据区域 Java 虚拟机在执行 Java 程序的过程中会把 ...

  8. win10,python连接mysql报”Can't connect to MySQL server on 'localhost' (10061)”

    一.环境及问题描述 1. 环境 操作系统:win10家庭版,64bit python版本:Python 2.7.15 mysql版本:mysql 5.4.3 2. 问题描述 最近跟公司申请电脑,预装w ...

  9. SpringMVC学习总结(一)--Hello World入门

    一.什么是Spring MVC Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面.Spring 框架提供了构建 Web 应用程序的全功能 ...

  10. JAVA里的CAS算法简析

    Atomic 从JDK5开始, java.util.concurrent包里提供了很多面向并发编程的类. 使用这些类在多核CPU的机器上会有比较好的性能.主要原因是这些类里面大多使用(失败-重试方式的 ...