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

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

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. windows解压缩版MySQL5.6.40的安装

    windows解压缩版MySQL5.6.40的安装 安装步骤: 1.下载mysql-5.6.40-winx64.zip https://cdn.mysql.com//Downloads/MySQL-5 ...

  2. Android开发:实时处理摄像头预览帧视频------浅析PreviewCallback,onPreviewFrame,AsyncTask的综合应用(转)

    原文地址:http://blog.csdn.net/yanzi1225627/article/details/8605061# 很多时候,android摄像头模块不仅预览,拍照这么简单,而是需要在预览 ...

  3. maven 统一管理依赖的版本号

  4. awk编程基础

    一.awk介绍 awk(名字来源于三个创始人姓氏首字母)是linux系统下文本编辑工具,是一门编程语言,有自己的基本语法和流程控制.函数.awk简单高效.   二.awk的运行方法 例子:使用冒号:分 ...

  5. Linux基石【第二篇】虚拟网络三种连接方式(转载)

    在虚拟机上安装完Centos系统后,开始配置静态IP,以方便在本宿主机上可以访问虚拟机,在曲折的配置中,了解到虚拟机还有三种连接方式:Bridged,NAT和Host-only,于是,我又一轮新的各种 ...

  6. 微信H5支付常见问题汇总

    常见问题 一.回调页面 正常流程用户支付完成后会返回至发起支付的页面,如需返回至指定页面,则可以在MWEB_URL后拼接上redirect_url参数,来指定回调页面. 如,您希望用户支付完成后跳转至 ...

  7. sqlserver 必须声明标量变量 "***"。

    发现在navicat premium上执行报这个异常,在sqlserver上不报,想到我之前的文章用存储过程时mysql里有个分割符,去掉“:”果然执行成功. DECLARE @countlmc IN ...

  8. 22-python爬虫解决gbk乱码问题

    转载自: python爬虫解决gbk乱码问题   今天尝试了下爬虫,爬取一本小说,忘语的凡人修仙仙界篇,当然这样不好,大家要支持正版. 爬取过程中是老套路,先获取网页源代码 # -*- coding: ...

  9. curl模拟多线程抓取网页(优化)

    通过上篇文章清楚了通过curl_multi_*函数可以一次请求多个url,但是也留下了问题,就是结果要等所有数据请求结束一起返回,才能逐个处理数据.优化代码,使先成功请求的url先返回处理结果,而不是 ...

  10. 有关jQuery valid 验证多个同name属性的input的问题

    今天遇到需要动态添加多个同name属性的input框,用jQuery valid进行验证时,没有指定不同的id,验证只会在第一个显示提示信息,因为jQuery valid显示的提示信息是根据每个inp ...