下面分别创建三张表,并分别插入1W条简单的数据用来测试,详情如下:
[1] test_a 有主键但无索引
 
CREATE TABLE `test_a` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `content` text NOT NULL,
  `number` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
 
[2] test_b 有主键和单列索引
 
CREATE TABLE `test_b` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `content` text NOT NULL,
  `number` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `titleIndex` (`title`) USING BTREE,
  UNIQUE KEY `numberIndex` (`number`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
 
[3] test_c 有主键和组合索引
 
CREATE TABLE `test_c` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `content` text NOT NULL,
  `number` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `titleNumberIndex` (`title`,`number`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
 
下面按照单列索引和组合索引分别对以上三张表进行查询测试,另外下面的时间都是多次测试取的平均值。
 
[1] 单列索引
 
[1.1] 查询指定的字段
 
[SQL] SELECT * FROM test_a WHERE title = 'title_5000';
[USE] 12ms
[SQL] SELECT * FROM test_b WHERE title = 'title_5000';
[USE] <1ms
 
说明:可以看到未加索引时间为12ms,加索引后小于1ms,还是相差很大的。
 
[SQL] SELECT * FROM test_a WHERE content = 'content_5000';
[USE] 13ms
[SQL] SELECT * FROM test_b WHERE content = 'content_5000';
[USE] 13ms
 
说明:由于content字段都未加索引,因此时间基本一致。
 
[1.2] 测试LIKE查询
 
[SQL] SELECT * FROM test_a WHERE title LIKE '%5000';
[USE] 13ms
[SQL] SELECT * FROM test_b WHERE title LIKE '%5000';
[USE] 13ms
说明:两者用时基本一致,因此索引并未命中。
 
[SQL] SELECT * FROM test_a WHERE title LIKE '5000%';
[USE] 12ms
[SQL] SELECT * FROM test_b WHERE title LIKE '5000%';
[USE] <1ms
 
说明:如果LIKE是前缀匹配则会命中索引,否则不会命中。另外以上的查询结果为空,但是不影响说明索引的作用。
 
[1.3] 测试OR语句
 
[SQL] SELECT * FROM test_a WHERE title = 'title_5000' OR content = 'content_5000';
[USE] 13ms
[SQL] SELECT * FROM test_b WHERE title = 'title_5000' OR content = 'content_5000';
[USE] 13ms
说明:两者用时基本一致,因此索引并未命中。
 
[SQL] SELECT * FROM test_a WHERE title = 'title_5000' OR number = '5000';
[USE] 13ms
[SQL] SELECT * FROM test_b WHERE title = 'title_5000' OR number = '5000';
[USE] <1ms
 
说明:如果OR两边的字段都加索引则命中,否则只有一个加索引则不命中。
 
[1.4] 测试IN语句
 
[SQL] SELECT * FROM test_a WHERE title IN('title_4999','title_5000','title_5001');
[USE] 12ms
[SQL] SELECT * FROM test_b WHERE title IN('title_4999','title_5000','title_5001');
[USE] <1ms
 
说明:IN语句也是可以命中索引的。
 
[1.5] 测试(BETWEEN,>,>=,<,<=)语句
 
[SQL] SELECT * FROM test_a WHERE number <= 5000;
[USE] 14ms
[SQL] SELECT * FROM test_b WHERE number <= 5000;
[USE] 14ms
[SQL] SELECT * FROM test_a WHERE number < 5000;
[USE] 14ms
[SQL] SELECT * FROM test_b WHERE number < 5000;
[USE] 14ms
[SQL] SELECT * FROM test_a WHERE number > 5000;
[USE] 14ms
[SQL] SELECT * FROM test_b WHERE number > 5000;
[USE] 14ms
[SQL] SELECT * FROM test_a WHERE number >= 5000;
[USE] 14ms
[SQL] SELECT * FROM test_b WHERE number >= 5000;
[USE] 14ms
[SQL] SELECT * FROM test_b FORCE INDEX(numberIndex) WHERE number >= 5000;
[USE] 14ms
[SQL] SELECT * FROM test_a WHERE number BETWEEN 4999 AND 5001;
[USE] 11ms
[SQL] SELECT * FROM test_b WHERE number BETWEEN 4999 AND 5001;
[USE] <1ms
 
说明:BETWEEN可以命中索引,其他比较符号未命中索引,强制使用索引效果也不明显,这个应该是与MySQL的索引足够性判断,如果索引大于30%就会使用全表扫描,具体待我查证后再详细介绍。
 
[1.6] 字段使用函数
 
[SQL] SELECT * FROM test_a WHERE SUBSTR(title,7,4) = '5000';
[USE] 13ms
[SQL] SELECT * FROM test_b WHERE SUBSTR(title,7,4) = '5000';
[USE] 13ms
 
说明:对字段使用函数则不能命中索引。
 
[2] 组合索引
 
[2.1] 测试OR语句
 
[SQL] SELECT * FROM test_a WHERE title = 'title_5000' OR content = 'content_5000';
[USE] 13ms
[SQL] SELECT * FROM test_c WHERE title = 'title_5000' OR content = 'content_5000';
[USE] 13ms
 
说明:组合索引中的OR语句没有命中索引。
 
[2.2] 测试AND语句
 
[SQL] SELECT * FROM test_a WHERE title = 'title_5000' AND number = 5000;
[USE] 12ms
[SQL] SELECT * FROM test_c WHERE title = 'title_5000' AND number = 5000;
[USE] <1ms
[SQL] SELECT * FROM test_a WHERE number = 5000;
[USE] 12ms
[SQL] SELECT * FROM test_c WHERE number = 5000;
[USE] 12ms
[SQL] SELECT * FROM test_a WHERE title = 'title_5000';
[USE] 12ms
[SQL] SELECT * FROM test_c WHERE title = 'title_5000';
[USE] <1ms
 
说明:以上证明了最左前缀匹配原则。
 
 
MySQL中EXPLAIN解释命令
EXPLAIN命令显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。
使用方法,在select语句前加上explain就可以了,如:
1
explain select surname,first_name form a,b where a.id=b.id
EXPLAIN列的解释:
table:显示这一行的数据是关于哪张表的
type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL
possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
key:实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引
key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好
ref:显示索引的哪一列被使用了,如果可能的话,是一个常数
rows:MYSQL认为必须检查的用来返回请求数据的行数
Extra:关于MYSQL如何解析查询的额外信息。将在表4.3中讨论,但这里可以看到的坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢
extra列返回的描述的意义
Distinct:一旦MYSQL找到了与行相联合匹配的行,就不再搜索了
Not exists: MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了
Range checked for each Record(index map:#):没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一
Using filesort: 看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行
Using index: 列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候
Using temporary 看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上
Where used 使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)
system 表只有一行:system表。这是const连接类型的特殊情况
const:表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待
eq_ref:在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用
ref:这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好
range:这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况
index: 这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)
ALL:这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免

MySQL索引优化实例说明的更多相关文章

  1. MySql 索引优化实例

    查询语句 SELECT customer_id,title,content FROM `product_comment` WHERE audit_status=1 AND product_id=199 ...

  2. mysql sql优化实例

    mysql sql优化实例 优化前: pt-query-degist分析结果: # Query 3: 0.00 QPS, 0.00x concurrency, ID 0xDC6E62FA021C85B ...

  3. mysql索引优化

    mysql 索引优化 >mysql一次查询只能使用一个索引.如果要对多个字段使用索引,建立复合索引. >越小的数据类型通常更好:越小的数据类型通常在磁盘.内存和CPU缓存中都需要更少的空间 ...

  4. Mysql 索引优化分析

    MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...

  5. 知识点:Mysql 索引优化实战(3)

    知识点:Mysql 索引原理完全手册(1) 知识点:Mysql 索引原理完全手册(2) 知识点:Mysql 索引优化实战(3) 知识点:Mysql 数据库索引优化实战(4) 索引原理知识回顾 索引的性 ...

  6. MySQL索引优化步骤总结

    在项目使用mysql过程中,随着系统的运行,发现一些慢查询,在这里总结一下mysql索引优化步骤 1.开发过程优化 开发过程中对业务表中查询sql分析sql执行计划(尤其是业务流水表),主要是查看sq ...

  7. MySQL索引优化看这篇文章就够了!

    阅读本文大概需要 5 分钟. 来源:cnblogs.com/songwenjie/p/9410009.html 本文主要讨论MySQL索引的部分知识.将会从MySQL索引基础.索引优化实战和数据库索引 ...

  8. mysql索引优化比普通查询速度快多少

    mysql索引优化比普通查询速度快多少 一.总结 一句话总结:普通查询全表查询,速度较慢,索引优化的话拿空间换时间,一针见血,所以速度要快很多. 索引优化快很多 空间换时间 1.软件层面优化数据库查询 ...

  9. mySql索引优化分析

    MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...

随机推荐

  1. 去掉Windows桌面软件的快捷图标的箭头

    去掉Windows桌面软件的快捷图标的箭头 怎么去除桌面快捷方式图标箭头 cmd /k reg delete "HKEY_CLASSES_ROOT\lnkfile" /v IsSh ...

  2. 监听 window.open 打开的窗口关闭并回调

    第三方的登录的解决方案通常有两种方式,一是打开一个新的标签页,然后登录回调回来: 二是通过父窗口打开一个子窗体去第三方登录,登陆成功时关掉子窗体回到父窗口. 问题来了 我的父窗体怎么样才知道子窗体被关 ...

  3. Centos 6.5安装Python3.6

    好不容易在Centos 6.5上安装成功Python3.6,在这里记录出来,以帮助其他的人第一次不要花太多时间.总的来看,步骤很简单,新手网上搜资料,可能是对于一些问题的解决方案,对于第一次安装可能麻 ...

  4. Bootstrap中的datetimepicker用法,只看一眼就全懂了

    本文实例为大家分享了bootstrap datetimepicker日期插件的简单使用,供大家参考,具体内容如下 首先在文件头部引入必要的文件: 1 2 <link rel="styl ...

  5. 201671010121 2016-2017-2《java程序设计》第一周学习总结

    之前学了些C语言,学的也不是太懂,还算能读懂一些简答的代码吧,我觉得这就是进步.刚步入大二,在计算机这个专业里不刻苦是不行的.但是,到我拿到Java书的时候,真心是吓住我了,好厚的一本书啊,不过在老师 ...

  6. Oracle03——游标、异常、存储过程、存储函数、触发器和Java代码访问Oracle对象

    作者: kent鹏 转载请注明出处: http://www.cnblogs.com/xieyupeng/p/7476717.html 1.游标(光标)Cursor 在写java程序中有集合的概念,那么 ...

  7. [js高手之路]深入浅出webpack教程系列3-配置文件webpack.config.js详解(下)

    本文继续接着上文,继续写下webpack.config.js的其他配置用法. 一.把两个文件打包成一个,entry怎么配置? 在上文中的webpack.dev.config.js中,用数组配置entr ...

  8. 移动端rem使用

    let $html=document.documentElement,windowW = window.innerWidth,ratio = windowW / 750if (windowW > ...

  9. Microsoft Visual Studio 打开代码出现乱码解决方案

    在用VS编写代码时,文本的字符集可能和编译器的字符集不同,在这种情况下代码会显示出乱码. 解决办法: 在VS的工具->选项里面找到"文本编辑器",勾选“自动检测不带签名的UT ...

  10. Spring MVC 解决无法访问静态文件和"全局异常处理"

    我们都知道,Spring MVC的请求都会去找controller控制器,若果我们页面中引入了一个外部样式,这样是没效果的, 我们引入样式的时候是通过<like href="...&q ...