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

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

1)先复习一下查询索引

  1. (Tue Jun :: ) db_1 >>show keys from xxxx; ==>(与show index from xxxx 是一样的)
  2. +--------------+------------+-------------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
  3. | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
  4. +--------------+------------+-------------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
  5. | xxxx | | PRIMARY | | iId | A | | NULL | NULL | | BTREE | | |
  6. | xxxx | | index_dPayTime | | dPayTime | A | | NULL | NULL | | BTREE | | |
  7. | xxxx | | index_sUserName | | sUserName | A | | NULL | NULL | | BTREE | | |
  8. | xxxx | | index_sPlatName | | iProxyId | A | | NULL | NULL | | BTREE | | |
  9. | xxxx | | index_sPlatName | | iServerId | A | | NULL | NULL | | BTREE | | |
  10. | xxxx | | index_sPlatName | | id | A | | NULL | NULL | YES | BTREE | | |
  11. | xxxx | | index_dPayDate | | dPayDate | A | | NULL | NULL | | BTREE | | |
  12. | xxxx | | Index_iPlatServerId_iPlayerId | | iPlatServerId | A | | NULL | NULL | | BTREE | | |
  13. | xxxx | | Index_iPlatServerId_iPlayerId | | iPlayerId | A | | NULL | NULL | | BTREE | | |
  14. | xxxx | | index_dPayDate_yue_iProxyId | | dPayDate_yue | A | | NULL | NULL | | BTREE | | |
  15. | xxxx | | index_dPayDate_yue_iProxyId | | iProxyId | A | | NULL | NULL | | BTREE | | |
  16. | 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 索引注释

我们要注意:

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

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

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

  1. select * from t_xxxx where pay_id in (
  2. 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"

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

  1. explain select * from t_xxxx where pay_id in (
  2. 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) > )

得到结果:

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

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

  1. 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) > ;
  2. Empty set (0.42 sec)
    0.42秒执行完毕

explain可以看到:

  1. +----+-------------+--------------+-------+----------------+----------------+---------+------+--------+----------------------------------------------+
  2. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  3. +----+-------------+--------------+-------+----------------+----------------+---------+------+--------+----------------------------------------------+
  4. | | SIMPLE | t_xxxx | range | index_dPayTime | index_dPayTime | | NULL | | Using where; Using temporary; Using filesort |
  5. +----+-------------+--------------+-------+----------------+----------------+---------+------+--------+----------------------------------------------+

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

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

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

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

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

  1. 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秒完成

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

  1. 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"
  1. +----+-------------+--------------+--------+----------------+------+---------+------+---------+----------------------------------------------+
  2. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  3. +----+-------------+--------------+--------+----------------+------+---------+------+---------+----------------------------------------------+
  4. | | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | | |
  5. | | PRIMARY | tpp1 | ALL | index_dPayTime | NULL | NULL | NULL | | Using where |
  6. | | DERIVED | t_xxxx | ALL | index_dPayTime | NULL | NULL | NULL | | Using where; Using temporary; Using filesort |
  7. +----+-------------+--------------+--------+----------------+------+---------+------+---------+----------------------------------------------+
    并没有命中索引

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

一次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. 如何使用C#程序给PDF文件添加编辑域

    PDF文档通常是不能编辑的,但有些时候需要在PDF文档中填写日期或签名之类,就需要在PDF有能编辑的文本域,本文介绍怎样用C#来实现这一功能. 环境 工具:VS2015 语言:C# 操作PDF类库:i ...

  2. Richview 首页 奇偶页 不同页眉页脚

    首页 奇偶页 不同页眉页脚 ScaleRichView v6.0 Different headers and footers for the first page, for odd and even ...

  3. 2015年传智播客JavaEE 第168期就业班视频教程day45-ERP项目-01 10-类图结构分析设计

    运行astah-pro.bat,这是windows下运行的.astah-run.sh是Linux下运行的. 类结构视图的作用是描述类模型和模型与模型之间的关系,也就是说我们在这要把这个一对多和多对多的 ...

  4. for 续5

    -------siwuxie095                 (五)usebackq 主要用于路径或文件名有空格时的情况 (说白了,就是对 in 后面的括号内集合进行转义)     单靠看帮助文 ...

  5. Ubuntu开机自动挂载分区

    虽然我基本上都是使用Linux的,但是仍然有些时候需要切换到Windows(双系统),如果所有的分区都使用ext4等Linux分区格式,则在Windows下访问十分不方便. 因此,我一般会将一些两个系 ...

  6. Java文件下载详解

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException ...

  7. 在Linux下访问Windows共享文件夹

    说明 以下操作以Ubuntu为例,大家可以参考. 我在Ubuntu 14.04和16.04都试过了. Windows共享文件夹 如果局域网内有一台Windows主机,将指定文件夹设为共享,就可以在局域 ...

  8. 一些使用的linux库

    1.curl网络库 apt-get install libcurl4-openssl-dev sudo apt-get install curl 2.jsoncpp库 sudo apt-get ins ...

  9. Java Thread系列(四)线程通信

    Java Thread系列(四)线程通信 一.传统通信 public static void main(String[] args) { //volatile实现两个线程间数据可见性 private ...

  10. 删除重复记录的最新sql脚本

    delete from tb1   where id in(select t2.minnum from(select MIN(t1.id) as minnum,t1.col1 as ars ,COUN ...