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. Listview 包含 edittext 的解决方案

    转载:https://blog.csdn.net/qq_28268507/article/details/53666576 一. 前几天在群里聊天,碰到一个哥们问listview的itemview中包 ...

  2. GCD HDU - 1695 (欧拉 + 容斥)

    GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  3. Java8的Stream语法详解(转载)

    1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel agg ...

  4. mongoDB 命令整理

    库操作 创建数据库 use [database] 查看数据库 show dbs 删除 db.dropDatabase() 备份 mongodump -h[host] ip -d[databasenam ...

  5. WC2019 题目集

    最近写的一些 WC2019 上讲的一些题.还是怕忘了,写点东西记录一下. LOJ2983 「WC2019」数树 题意 本题包含三个问题: 问题 0:已知两棵 \(n\) 个节点的树的形态(两棵树的节点 ...

  6. Vert.x系列(三)--ClusteredEventBus源码分析

    前言:因为ClusteredEventBus涉及集群,有必产生网络问题,从而引入了NetServer.ServerID等涉及网络,端口的类.在之前的EventBusImpl中, 使用的数据结构是以ad ...

  7. 【Loj117】有源汇上下界最小流(网络流)

    [Loj117]有源汇上下界最小流(网络流) 题面 Loj 题解 还是模板题. #include<iostream> #include<cstdio> #include< ...

  8. 【BZOJ5337】[TJOI2018]str(动态规划,哈希)

    [BZOJ5337][TJOI2018]str(动态规划,哈希) 题面 BZOJ 洛谷 题解 就很呆... 显然按层\(dp\),如果能够匹配上就进行转移,直接哈希判断是否能够匹配就好了... #in ...

  9. 群福利:Redis云服务器免费领取(附Redis安装和连接远程连接Redis案例)

    Redis安装:在线体验:https://try.redis.io Ubuntu:sudo apt-get install redis CentOS:yum install redis (root权限 ...

  10. 10元买啤酒问题Java解法

    10元去买啤酒,2元一瓶.每两个瓶可以换一瓶啤酒,每四个瓶盖可以换一瓶啤酒.最多买几瓶? public class Java { public static void main(String[] ar ...