MySQL查询的优化是个老生常谈的问题,方法更是多种多样,其中最直接的就是创建索引.

这里通过一个简单的demo来实际用一下索引,看看索引在百万级别查询中速率的提升效果如何

所需数据可以从我前面的一篇博客中获取:https://www.cnblogs.com/wangbaojun/p/11154515.html

有一张salaries,

  查看表结构如下: 

mysql> desc salaries;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no | int(11) | NO | PRI | NULL | |
| salary | int(11) | NO | | NULL | |
| from_date | date | NO | PRI | NULL | |
| to_date | date | NO | | NULL | |
+-----------+---------+------+-----+---------+-------+

  可以看到emp_no,from_date都是PRI(主键索引),这是在这个表中将这两个字段联合起来设置为主键,一张表中还是只能有一个主键

  查看表的创建命令:

  

mysql> show create table salaries;
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| salaries | CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`),
CONSTRAINT `salaries_ibfk_1` FOREIGN KEY (`emp_no`) REFERENCES `employees` (`emp_no`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

  注意我标红的地方,将emp_no`,`from_date设置为组合主键,组合索引遵从左前缀原则,查询emp_no,或者查询(`emp_no`,`from_date`)会走索引,但是查from_date不会走索引,可以看一下用explain命令查看:

mysql> explain select * from salaries where emp_no=227694;
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | salaries | ref | PRIMARY | PRIMARY | 4 | const | 18 | NULL | # key为PRIMARY 走了索引
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
1 row in set (0.01 sec) mysql> explain select * from salaries where from_date = '1986-06-26';
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | salaries | ALL | NULL | NULL | NULL | NULL | 2838426 | Using where | key为Null,Extra 使用了where,没走索引
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec) mysql> explain select * from salaries where from_date = '1986-06-26' and emp_no=75047;
+----+-------------+----------+-------+---------------+---------+---------+-------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+---------+---------+-------------+------+-------+
| 1 | SIMPLE | salaries | const | PRIMARY | PRIMARY | 7 | const,const | 1 | NULL | # key为PRIMARY 走了索引
 +----+-------------+----------+-------+---------------+---------+---------+-------------+------+-------+ 
1 row in set (0.00 sec)

  to_date字段没有设置索引,我们来测试一下加索引前后,该字段查询效率会不会有提升:

  未加索引:

  

mysql> select * from salaries where to_date = '1986-06-26';                                                                                                                                          +--------+--------+------------+------------+
| emp_no | salary | from_date | to_date |
+--------+--------+------------+------------+
| 25676 | 40000 | 1985-06-26 | 1986-06-26 |
| 28757 | 40000 | 1985-06-26 | 1986-06-26 |
| 30860 | 64620 | 1985-06-26 | 1986-06-26 |
| 69209 | 40000 | 1985-06-26 | 1986-06-26 |
| 80550 | 45292 | 1985-06-26 | 1986-06-26 |
| 91204 | 47553 | 1985-06-26 | 1986-06-26 |
| 96140 | 52908 | 1985-06-26 | 1986-06-26 |
| 208352 | 42989 | 1985-06-26 | 1986-06-26 |
| 213109 | 90133 | 1985-06-26 | 1986-06-26 |
| 217498 | 80247 | 1985-06-26 | 1986-06-26 |
| 219462 | 83880 | 1985-06-26 | 1986-06-26 |
| 223150 | 40000 | 1985-06-26 | 1986-06-26 |
| 227694 | 73897 | 1985-06-26 | 1986-06-26 |
| 232856 | 73126 | 1985-06-26 | 1986-06-26 |
| 237619 | 56982 | 1985-06-26 | 1986-06-26 |
| 244087 | 40000 | 1985-06-26 | 1986-06-26 |
| 253472 | 72004 | 1985-06-26 | 1986-06-26 |
| 257395 | 40000 | 1985-06-26 | 1986-06-26 |
| 261811 | 40000 | 1985-06-26 | 1986-06-26 |
| 268968 | 40000 | 1985-06-26 | 1986-06-26 |
| 269331 | 40000 | 1985-06-26 | 1986-06-26 |
| 274805 | 40000 | 1985-06-26 | 1986-06-26 |
| 279432 | 74530 | 1985-06-26 | 1986-06-26 |
| 285685 | 83198 | 1985-06-26 | 1986-06-26 |
| 286745 | 44082 | 1985-06-26 | 1986-06-26 |
| 290901 | 49876 | 1985-06-26 | 1986-06-26 |
| 400719 | 79168 | 1985-06-26 | 1986-06-26 |
| 401448 | 49600 | 1985-06-26 | 1986-06-26 |
| 427374 | 40000 | 1985-06-26 | 1986-06-26 |
| 432024 | 40000 | 1985-06-26 | 1986-06-26 |
| 432654 | 40000 | 1985-06-26 | 1986-06-26 |
| 438461 | 44451 | 1985-06-26 | 1986-06-26 |
| 446228 | 42733 | 1985-06-26 | 1986-06-26 |
| 447391 | 62381 | 1985-06-26 | 1986-06-26 |
| 448823 | 40000 | 1985-06-26 | 1986-06-26 |
| 452355 | 40000 | 1985-06-26 | 1986-06-26 |
| 453590 | 61615 | 1985-06-26 | 1986-06-26 |
| 456521 | 40000 | 1985-06-26 | 1986-06-26 |
| 464415 | 48955 | 1985-06-26 | 1986-06-26 |
| 467901 | 52349 | 1985-06-26 | 1986-06-26 |
| 472895 | 40000 | 1985-06-26 | 1986-06-26 |
| 476501 | 40000 | 1985-06-26 | 1986-06-26 |
| 477079 | 40000 | 1985-06-26 | 1986-06-26 |
| 478934 | 55054 | 1985-06-26 | 1986-06-26 |
| 480301 | 44177 | 1985-06-26 | 1986-06-26 |
| 484507 | 40000 | 1985-06-26 | 1986-06-26 |
| 486187 | 40000 | 1985-06-26 | 1986-06-26 |
| 491159 | 46034 | 1985-06-26 | 1986-06-26 |
| 493154 | 40000 | 1985-06-26 | 1986-06-26 |
| 498140 | 81909 | 1985-06-26 | 1986-06-26 |
| 498565 | 72853 | 1985-06-26 | 1986-06-26 |
+--------+--------+------------+------------+
51 rows in set (1.08 sec)

  用explain分析一下:

  

mysql> explain select * from salaries where to_date = '1986-06-26';
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | salaries | ALL | NULL | NULL | NULL | NULL | 2838426 | Using where | # Extra使用where。key为Null,在2838426条数据中找51条记录用时1.08s
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

  

  为to_date字段加索引:

mysql> create index to_date on salaries(to_date);
Query OK, 0 rows affected (5.31 sec)
Records: 0 Duplicates: 0 Warnings: 0                                   创建索引会耗时,索然提升了查询速率,但是更新添加动作会效率降低

 现在看一下表结构:

  

mysql> desc salaries;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no | int(11) | NO | PRI | NULL | |
| salary | int(11) | NO | | NULL | |
| from_date | date | NO | PRI | NULL | |
| to_date | date | NO | MUL | NULL | | MUL表示非唯一索引
+-----------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec) mysql> show create table salaries;
+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| salaries | CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`),
KEY `to_date` (`to_date`), # 创建了索引key为to_date
CONSTRAINT `salaries_ibfk_1` FOREIGN KEY (`emp_no`) REFERENCES `employees` (`emp_no`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

   再次查询:

   

mysql> select * from salaries where to_date = '1986-06-26';
+--------+--------+------------+------------+
| emp_no | salary | from_date | to_date |
+--------+--------+------------+------------+
| 25676 | 40000 | 1985-06-26 | 1986-06-26 |
| 28757 | 40000 | 1985-06-26 | 1986-06-26 |
| 30860 | 64620 | 1985-06-26 | 1986-06-26 |
| 69209 | 40000 | 1985-06-26 | 1986-06-26 |
| 80550 | 45292 | 1985-06-26 | 1986-06-26 |
| 91204 | 47553 | 1985-06-26 | 1986-06-26 |
| 96140 | 52908 | 1985-06-26 | 1986-06-26 |
| 208352 | 42989 | 1985-06-26 | 1986-06-26 |
| 213109 | 90133 | 1985-06-26 | 1986-06-26 |
| 217498 | 80247 | 1985-06-26 | 1986-06-26 |
| 219462 | 83880 | 1985-06-26 | 1986-06-26 |
| 223150 | 40000 | 1985-06-26 | 1986-06-26 |
| 227694 | 73897 | 1985-06-26 | 1986-06-26 |
| 232856 | 73126 | 1985-06-26 | 1986-06-26 |
| 237619 | 56982 | 1985-06-26 | 1986-06-26 |
| 244087 | 40000 | 1985-06-26 | 1986-06-26 |
| 253472 | 72004 | 1985-06-26 | 1986-06-26 |
| 257395 | 40000 | 1985-06-26 | 1986-06-26 |
| 261811 | 40000 | 1985-06-26 | 1986-06-26 |
| 268968 | 40000 | 1985-06-26 | 1986-06-26 |
| 269331 | 40000 | 1985-06-26 | 1986-06-26 |
| 274805 | 40000 | 1985-06-26 | 1986-06-26 |
| 279432 | 74530 | 1985-06-26 | 1986-06-26 |
| 285685 | 83198 | 1985-06-26 | 1986-06-26 |
| 286745 | 44082 | 1985-06-26 | 1986-06-26 |
| 290901 | 49876 | 1985-06-26 | 1986-06-26 |
| 400719 | 79168 | 1985-06-26 | 1986-06-26 |
| 401448 | 49600 | 1985-06-26 | 1986-06-26 |
| 427374 | 40000 | 1985-06-26 | 1986-06-26 |
| 432024 | 40000 | 1985-06-26 | 1986-06-26 |
| 432654 | 40000 | 1985-06-26 | 1986-06-26 |
| 438461 | 44451 | 1985-06-26 | 1986-06-26 |
| 446228 | 42733 | 1985-06-26 | 1986-06-26 |
| 447391 | 62381 | 1985-06-26 | 1986-06-26 |
| 448823 | 40000 | 1985-06-26 | 1986-06-26 |
| 452355 | 40000 | 1985-06-26 | 1986-06-26 |
| 453590 | 61615 | 1985-06-26 | 1986-06-26 |
| 456521 | 40000 | 1985-06-26 | 1986-06-26 |
| 464415 | 48955 | 1985-06-26 | 1986-06-26 |
| 467901 | 52349 | 1985-06-26 | 1986-06-26 |
| 472895 | 40000 | 1985-06-26 | 1986-06-26 |
| 476501 | 40000 | 1985-06-26 | 1986-06-26 |
| 477079 | 40000 | 1985-06-26 | 1986-06-26 |
| 478934 | 55054 | 1985-06-26 | 1986-06-26 |
| 480301 | 44177 | 1985-06-26 | 1986-06-26 |
| 484507 | 40000 | 1985-06-26 | 1986-06-26 |
| 486187 | 40000 | 1985-06-26 | 1986-06-26 |
| 491159 | 46034 | 1985-06-26 | 1986-06-26 |
| 493154 | 40000 | 1985-06-26 | 1986-06-26 |
| 498140 | 81909 | 1985-06-26 | 1986-06-26 |
| 498565 | 72853 | 1985-06-26 | 1986-06-26 |
+--------+--------+------------+------------+
51 rows in set (0.00 sec) # 创建索引后同样的查询条件从1.08s变为了0.00s,惊讶吧

  explain分析:

  

mysql> explain select * from salaries where to_date = '1986-06-26';
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | salaries | ref | to_date | to_date | 3 | const | 51 | NULL | key从Null变味了索引字段to_date,row从两百多万变为了51
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)

  这个demo从数据上直观的体现了索引带来的查询效率提升有多可观,但是索引也是有利必有害,更多索引的底层知识可以参考这位大牛的博客:https://www.cnblogs.com/Aiapple/p/5693239.html

  

在Mysql中使用索引的更多相关文章

  1. MySQL(五) MySQL中的索引详讲

    序言 之前写到MySQL对表的增删改查(查询最为重要)后,就感觉MySQL就差不多学完了,没有想继续学下去的心态了,原因可能是由于别人的影响,觉得对于MySQL来说,知道了一些复杂的查询,就够了,但是 ...

  2. 一、MySQL中的索引 二、MySQL中的函数 三、MySQL数据库的备份和恢复 四、数据库设计和优化(重点)

    一.MySQL中的索引###<1>索引的概念 索引就是一种数据结构(高效获取数据),在mysql中以文件的方式存在.存储建立了索引列的地址或者指向. 文件 :(以某种数据 结构存放) 存放 ...

  3. MySQL中的索引详讲

    一.什么是索引?为什么要建立索引? 索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的 ...

  4. mysql 中添加索引的三种方法

    原文:http://www.andyqian.com/2016/04/06/database/mysqleindex/ 在mysql中有多种索引,有普通索引,全文索引,唯一索引,多列索引,小伙伴们可以 ...

  5. (转)MySQL中的索引详讲

    序言 之前写到MySQL对表的增删改查(查询最为重要)后,就感觉MySQL就差不多学完了,没有想继续学下去的心态了,原因可能是由于别人的影响,觉得对于MySQL来说,知道了一些复杂的查询,就够了,但是 ...

  6. MySQL中是索引

    MySQL中是索引: --.唯一索引: 一行中的内容不能一样, create t2( id int , num int, unique weiyisuiyin (id,num) ) --唯一; --约 ...

  7. 一步一步带你入门MySQL中的索引和锁 (转)

    出处: 一步一步带你入门MySQL中的索引和锁 索引 索引常见的几种类型 索引常见的类型有哈希索引,有序数组索引,二叉树索引,跳表等等.本文主要探讨 MySQL 的默认存储引擎 InnoDB 的索引结 ...

  8. MySQL中的索引优化

    MySQL中的SQL的常见优化策略 MySQL中的索引优化 MySQL中的索引简介 过多的使用索引将会造成滥用.因此索引也会有它的缺点.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 ...

  9. MySQL中的索引简介

    MySQL中的SQL的常见优化策略 MySQL中的索引优化 MySQL中的索引简介 一. 索引的优点 为什么要创建索引?这是因为,创建索引可以大大提高系统的查询性能. 第一.通过创建唯一性索引,可以保 ...

  10. java面试一日一题:讲下mysql中的索引

    问题:请讲下mysql中的索引 分析:mysql中有很多索引,要对对这些索引有所掌握,还要弄清楚每种索引的本质? 回答要点: 主要从以下几点去考虑 1.索引的本质是什么 2.mysql的索引分类: 3 ...

随机推荐

  1. mysql安装报错error: Header V3 DSA signature: BAD, key ID

    CentOS安装rpm安装MySQL时爆出警告: warning: mysql-community-server-5.7.18-1.el6.x86_64.rpm: Header V3 DSA/SHA1 ...

  2. iOS实现页面既显示WebView,WebView下显示TableView,动态计算WebView内容高度

    实现效果如下: 忽略底部的评论视图,太丑了,待完善...... 实现思路: 1>页面布局采用TableView实现,顶部"关注"模块的View是TableView的table ...

  3. wdScrollTab

    wdScrollTab是一个采用jQuery实现的Tab面板,当标签太多超出页面时会自动滚动.支持iframe.ajax调用和动态加载内容.

  4. 【HANA系列】SAP HANA SQL IFNULL和NULLIF用法与区别

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL IFN ...

  5. Leetcode之动态规划(DP)专题-198. 打家劫舍(House Robber)

    Leetcode之动态规划(DP)专题-198. 打家劫舍(House Robber) 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互 ...

  6. 内存块是一种数据结构,内核对象&句柄

    内核对象&句柄 目录 1 内核对象的概念 2 内核对象的使用计数 3 句柄 4 句柄表   项目工程代码中设计句柄的使用,一时不知句柄是何物,通过查阅自学之后,对句柄及其使用有一个初步的了解. ...

  7. 记录解决一个项目中遇到的maven打包问题

    拿到同时给的代码,进行打jar包,这个jar包依赖一个第三方的jar包,一开始用IDEA打出来的包,没有把依赖的包打进去,后来查了相关的资料, 发现需要在maven的pom中添加相关的maven插件, ...

  8. java知识随笔整理-Oracle存储过程优缺点

    优点: 1.存储过程可以使得程序执行效率更高.安全性更好. 2.建立过程不会很耗系统资源,因为过程只是在调用才执行. 3.存储过程可以用于降低网络流量,存储过程代码直接存储于数据库中,所以不会产生大量 ...

  9. Luogu P2495 [SDOI2011]消耗战

    题目 我们可以很快的想到一个单次\(O(n)\)的dp. 然后我们注意到这个dp有很多无用的操作,比如一条没有关键点的链可以直接去掉. 所以我们可以尝试一次dp中只管那些有用的点. 题目给的关键点显然 ...

  10. java爬取并下载酷狗TOP500歌曲

    是这样的,之前买车送的垃圾记录仪不能用了,这两天狠心买了好点的记录仪,带导航.音乐.蓝牙.4G等功能,寻思,既然有这些功能就利用起来,用4G听歌有点奢侈,就准备去酷狗下点歌听,居然都是需要办会员才能下 ...