MySQL主要提供2种方式的索引:B-Tree索引,Hash索引

B树索引具有范围查找和前缀查找的能力,对于有N节点的B树,检索一条记录的复杂度为O(LogN)。相当于二分查找。

哈希索引只能做等于查找,但是无论多大的Hash表,查找复杂度都是O(1)。

显然,如果值的差异性大,并且以等值查找(=、 <、>、in)为主,Hash索引是更高效的选择,它有O(1)的查找复杂度。

如果值的差异性相对较差,并且以范围查找(between and)为主,B树是更好的选择,它支持范围查找。

索引

无论是面试,还是实际工作中,对于一个Java程序员来说,数据库优化是避不开的一个技术点,关于数据库的优化,在性能达不到要求的情况下,我大致给出以下几个方向:

(1)优化表结构,对常用字段和非常用的字段分开存储

(2)优化SQL,合理使用索引

(3)做数据库读写分离,减少IO压力,由于数据库对记录做了持久化并存储在磁盘上,对磁盘的I/O又是非常消耗性能的操作,因此读、写都在一个库中会大大增加I/O的压力

(4)尝试使用缓存,不要让数据都走数据库

(5)对业务做垂直拆分

(6)对表做水平拆分,这一步比较麻烦,要注意主键生成规则以及请求路由规则

以上6个点是有优先级的,本文关注的是第二点的索引部分。正确合理地使用索引对于数据库性能提升是至关重要的,本文暂时不分析索引原理,只是从实战的角度,总结一下索引的使用技巧,理论结合实践,印象会更深一些。

当然,事前我已经建立了一张很简单的student表并向表中插入了10万条数据,SQL为:

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`s_id` int(11) NOT NULL AUTO_INCREMENT,
`s_name` varchar(100) DEFAULT NULL,
`s_age` int(11) DEFAULT NULL,
`s_phone` varchar(30) DEFAULT NULL,
PRIMARY KEY (`s_id`),
KEY `s_name` (`s_name`)
) ENGINE=InnoDB, CHARSET=utf8;

使用普通索引与不使用普通索引的区别

先看一下不使用普通索引,进行查询,执行SQL语句:

select * from student where s_name = "99999ssss";

看一下查询时间:

花费了0.179秒,使用explain查看一下该条SQL语句的执行情况:

分析几个关键信息:

  • select_type:SIMPLE,这个不是很关键,只是表示这是一次简单的查询,没有join,没有union,没有中间表
  • type:ALL,表示该次SQL进行了全表查询
  • key:MySQL使用的索引名,这里null表示此次SQL查询MySQL并没有使用索引
  • rows:这个是最关键的,表示这次SQL查询了100665条记录

OK,接下来给s_name这一列加上普通索引:

alter table student add index s_name(s_name);

看一下运行结果:

看到在s_name上加上索引之后,查询速度马上快了3倍以上。

从分析结果上来看,由于此次SQL对列s_name使用了索引,因此rows只查了1条记录,大大提升了查询效率。

把索引建立在有大量重复数据的字段上

把索引建立在有大量重复数据的字段上,并不能有效地提升SQL效率,比如我的s_phone的取值为"00000000"~"99999999",此时对s_phone做查询,未加索引的时候:

看到这条select语句的查询时间是0.05秒,而给s_phone字段加了索引之后:

反而变为了0.064秒,并没有显著地提升查询效率,反而更加缓慢。通过explain语句,发现此次SQL通过索引查询了18000条rows,再去定位这18000多条数据,自然会慢一点。

这说明了,即使查询的时候用到了索引,也未必能提升查询的效率,索引建立在重复数据量很少的字段上效果才明显,但是这也将导致索引的增大,不过大多数时候这并不是太大的问题。

索引与like

不建议对索引列使用like语句,比如说执行以下两句SQL:

select * from student where s_name like "%99999ssss%";
select * from student where s_name like "%99999ssss";

看一下explain出来的结果,都是一样的:

发现没有用到索引,这是对索引列使用like的限制,要对索引列使用like,通配符只能在结尾,开头不可以有任何的通配符,比如:

select * from student where s_name like "99999ssss%";

此时再explain看一下:

看到这么实用like则使用到了索引,这不得不说是一个限制。

索引与函数

在索引列上使用MySQL函数也会导致索引失效,看一个例子:

select * from student where "99999ssss" = left(s_name, 9);

这条SQL语句非常好理解,查询s_name列中从左边开始截取9个字符后的字符串为"99999ssss"的记录,查看一下explain的结果:

结果很明显,没有用到索引,这表明对索引列使用函数将导致索引失效。

一个技巧是,依然使用=,但是索引列不使用函数而对常数项使用函数,这样索引就有效了,当然这条语句是无法这么优化的。

Mysql:索引实战的更多相关文章

  1. MySQL索引实战经验总结

    MySQL索引对数据检索的性能至关重要,盲目的增加索引不仅不能带来性能的提升,反而会消耗更多的额外资源,本篇总结了一些MySQL索引实战经验. 索引是用于快速查找记录的一种数据结构.索引就像是数据库中 ...

  2. mysql颠覆实战笔记(二)-- 用户登录(一):唯一索引的妙用

    版权声明:笔记整理者亡命小卒热爱自由,崇尚分享.但是本笔记源自www.jtthink.com(程序员在囧途)沈逸老师的<web级mysql颠覆实战课程 >.如需转载请尊重老师劳动,保留沈逸 ...

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

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

  4. MySQL索引介绍和实战

    索引是什么 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构. 可以得到索引的本质:索引是数据结构,索引的目的是提高查询效率,可以类比英语新华字典,根据目录定位词 ...

  5. Mysql之B+树索引实战

    索引代价 空间上的代价 一个索引都对应一棵B+树,树中每一个节点都是一个数据页,一个页默认会占用16KB的存储空间,所以一个索引也是会占用磁盘空间的. 时间上的代价 索引是对数据的排序,那么当对表中的 ...

  6. MySQL 索引原理概述及慢查询优化实战

    MySQL凭借着出色的性能.低廉的成本.丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库.虽然性能出色,但所谓“好马配好鞍”,如何能够更好的使用它,已经成为开发工程师的必修课,我们经常会从职位 ...

  7. mysql实战优化之四:mysql索引优化

    0. 使用SQL提示 用户可以使用use index.ignore index.force index等SQL提示来进行选择SQL的执行计划. 1.支持多种过滤条件 2.避免多个范围条件 应尽量避免在 ...

  8. 【真·干货】MySQL 索引及优化实战

    热烈推荐:超多IT资源,尽在798资源网 声明:本文为转载文章,为防止丢失所以做此备份. 本文来自公众号:GitChat精品课 原文地址:https://mp.weixin.qq.com/s/6V7h ...

  9. MYSQL索引结构原理、性能分析与优化

    [转]MYSQL索引结构原理.性能分析与优化 第一部分:基础知识 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里, 不用一页一页 ...

  10. mysql颠覆实战笔记(一)--设计一个项目需求,灌入一万数据先

    版权声明:笔记整理者亡命小卒热爱自由,崇尚分享.但是本笔记源自www.jtthink.com(程序员在囧途)沈逸老师的<web级mysql颠覆实战课程 >.如需转载请尊重老师劳动,保留沈逸 ...

随机推荐

  1. scrapy爬取知乎问答

    登陆 参考 https://github.com/zkqiang/Zhihu-Login # -*- coding: utf-8 -*- import scrapy import time impor ...

  2. Yahoo Programming Contest 2019 补题记录(DEF)

    D - Ears 题目链接:D - Ears 大意:你在一个\(0-L\)的数轴上行走,从整数格出发,在整数格结束,可以在整数格转弯.每当你经过坐标为\(i-0.5\)的位置时(\(i\)是整数),在 ...

  3. 我的POI代码库(持续更新)

    添加的maven依赖是 <poi.version>3.15</poi.version> ... <dependency> <groupId>org.ap ...

  4. [APIO2012]守卫

    近日状态并不是很好, 很不稳, 思路也不是很清晰 希望自己能走出来 题意:有序列1~n 现给出两种区间 区间0:序号在[x, y]的节点不能有忍者 区间1:序号在[x, y]的节点区间里至少有一个忍者 ...

  5. Square(斯特林反演)

    题意 给出一个 \(n × m\) 大小的矩形,每个位置可以填上 \([1, c]\) 中的任意一个数,要求填好后任意两行互不等价且任意两列互不等价,两行或两列等价当且仅当对应位置完全相同,求方案数 ...

  6. zabbix3.4.6之自动发现与自动注册

    在zabbix中添加新主机时,是需要手动添加,但在zabbix的Action里有两项功能,自动发现与自动注册,运用这两个功能中任意一个都可以实现自动添加机器,但添加的主机名是IP地址. 自动发现:添加 ...

  7. 【BZOJ2137】submultiple(数论)

    [BZOJ2137]submultiple(数论) 题面 BZOJ 题解 首先不难发现答案就是:\(\displaystyle\prod_{i=1}^n (\sum_{j=1}^{p_i+1}j^k) ...

  8. 【转】STM32擦除内部FLASH时间过长导致IWDG复位分析

    @20119-01-29 [小记] STM32擦除内部FLASH时间过长导致IWDG复位分析

  9. 【linux】/dev/null作用和/dev/random

    一.  /dev/null /dev/null属于字符特殊文件,它属于空设备,是一个特殊的设备文件,它会丢弃一切写入其中的数据,写入它的内容都会永远丢失,而且没有任何可以读取的内容. 我们用file命 ...

  10. ArcGIS for qml -设置地图和视域中心

    源码:https://github.com/sueRimn/ArcGIS-for-qml-demos 作者: 狐狸家的鱼 Github: 八至 版权声明:如需转载请获取授权和联系作者 ArcGIS R ...