最全面的 MySQL 索引详解
什么是索引?
1、索引
索引是表的目录,在查找内容之前可以先在目录中查找索引位置,以此快速定位查询数据。对于索引,会保存在额外的文件中。
2、索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构。类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可。
索引由数据库中一列或多列组合而成,其作用是提高对表中数据的查询速度
索引的优点是可以提高检索数据的速度
索引的缺点是创建和维护索引需要耗费时间
索引可以提高查询速度,会减慢写入速度
索引分类
1.普通索引
2.唯一索引
3.全文索引
4.单列索引
5.多列索引
6.空间索引
7.主键索引
8.组合索引
- 普通索引:仅加速查询
- 唯一索引:加速查询 + 列值唯一(可以有null)
- 主键索引:加速查询 + 列值唯一 + 表中只有一个(不可以有null)
- 组合索引:多列值组成一个索引,
专门用于组合搜索,其效率大于索引合并 - 全文索引:对文本的内容进行分词,进行搜索
索引合并,使用多个单列索引组合搜索
覆盖索引,select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖
如何创建索引?记住一个单词—explain
创建表的时候创建索引
- CREATE TABLE tbl_name(
- 字段名称 字段类型 [完整性约束条件],
- ,,,,
- [UNIQUE|FULLTEXT|SPATIAL] INDEX|KEY[索引名称](字段名称[(长度)])
- [ASC|DESC]
- );
在已经存在的表上创建索引:
- .CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX 索引名称 ON 表名{字段名称[(长度)] [ASC|DESC]}
- .ALTER TABLE tbl_name ADD [UNIQUE|FULLTEXT|SPATIAL] INDEX索引名称(字段名称[(长度)][ASC|DESC]);
如何删除索引?
- DROP INDEX 索引名称 ON tbl_name
1.普通索引
普通索引仅有一个功能:加速查询
创建表+索引
- create table in1(
- nid int not null auto_increment primary key,
- name ) not null,
- email ) not null,
- extra text,
- index ix_name (name)
- )
创建索引
- create index index_name on table_name(column_name)
删除索引
- drop index_name on table_name;
查看索引
- show index from table_name;
注意:对于创建索引时如果是BLOB 和 TEXT 类型,必须指定length。
- ));
2、唯一索引
唯一索引有两个功能:加速查询 和 唯一约束(可含null)
创建表+唯一索引
- create table in1(
- nid int not null auto_increment primary key,
- name ) not null,
- email ) not null,
- extra text,
- unique ix_name (name)
- )
创建唯一索引
- create unique index 索引名 on 表名(列名)
删除唯一索引
- drop unique index 索引名 on 表名
3、主键索引
主键有两个功能:加速查询 和 唯一约束(不可含null)
创建表+创建主键
- create table in1(
- nid int not null auto_increment primary key,
- name ) not null,
- email ) not null,
- extra text,
- index ix_name (name)
- )
- OR
- create table in1(
- nid int not null auto_increment,
- name ) not null,
- email ) not null,
- extra text,
- primary key(ni1),
- index ix_name (name)
- )
创建主键
- alter table 表名 add primary key(列名);
删除主键
- alter table 表名 drop primary key;
- alter table 表名 modify 列名 int, drop primary key;
4、组合索引
组合索引是将n个列组合成一个索引
其应用场景为:频繁的同时使用n列来进行查询,如:where n1 = ‘alex’ and n2 = 666。
创建表
- create table in3(
- nid int not null auto_increment primary key,
- name ) not null,
- email ) not null,
- extra text
- )
创建组合索引
- create index ix_name_email on in3(name,email);
如上创建组合索引之后,查询:
- name and email – 使用索引
- name — 使用索引
- email — 不使用索引
注意:对于同时搜索n个条件时,组合索引的性能好于多个单一索引合并。
相关命令
- - 查看表结构
- desc 表名
- - 查看生成表的SQL
- show create table 表名
- - 查看索引
- show index from 表名
- - 查看执行时间
- ;
- SQL...
- show profiles;
使用索引和不使用索引
- 由于索引是专门用于加速搜索而生,所以加上索引之后,查询效率会快到飞起来。
- # 有索引
- mysql> select * from tb1 where name = 'wupeiqi-888';
- +-----+-------------+---------------------+----------------------------------+---------------------+
- | nid | name | email | radom | ctime |
- +-----+-------------+---------------------+----------------------------------+---------------------+
- :: |
- +-----+-------------+---------------------+----------------------------------+---------------------+
- row in set (0.00 sec)
- # 无索引
- mysql> select * from tb1 where email = 'wupeiqi888@live.com';
- +-----+-------------+---------------------+----------------------------------+---------------------+
- | nid | name | email | radom | ctime |
- +-----+-------------+---------------------+----------------------------------+---------------------+
- :: |
- +-----+-------------+---------------------+----------------------------------+---------------------+
- row in set (1.23 sec)
正确使用索引
数据库表中添加索引后确实会让查询速度起飞,但前提必须是正确的使用索引来查询,如果以错误的方式使用,则即使建立索引也会不奏效。
即使建立索引,索引也不会生效:
- - like '%xx'
- select * from tb1 where name like '%cn';
- - 使用函数
- select * from tb1 where reverse(name) = 'wupeiqi';
- - or
- or email = 'seven@live.com';
- 特别的:当or条件中有未建立索引的列才失效,以下会走索引
- or name = 'seven';
- or email = 'seven@live.com' and name = 'alex'
- - 类型不一致
- 如果列是字符串类型,传入条件是必须用引号引起来,不然...
- ;
- - !=
- select * from tb1 where name != 'alex'
- 特别的:如果是主键,则还是会走索引
- - >
- select * from tb1 where name > 'alex'
- 特别的:如果是主键或索引是整数类型,则还是会走索引
- - order by
- select email from tb1 order by name desc;
- 当根据索引排序时候,选择的映射如果不是索引,则不走索引
- 特别的:如果对主键排序,则还是走索引:
- select * from tb1 order by nid desc;
- - 组合索引最左前缀
- 如果组合索引为:(name,email)
- name and email -- 使用索引
- name -- 使用索引
- email -- 不使用索引
其他注意事项
- - 避免使用select *
- )或count(列) 代替 count(*)
- - 创建表时尽量时 char 代替 varchar
- - 表的字段顺序固定长度的字段优先
- - 组合索引代替多个单列索引(经常使用多个条件查询时)
- - 尽量使用短索引
- - 使用连接(JOIN)来代替子查询(Sub-Queries)
- - 连表时注意条件类型需一致
- - 索引散列值(重复少)不适合建索引,例:性别不适合
limit分页
无论是否有索引,limit分页是一个值得关注的问题
- 每页显示10条:
- 当前 ,
- 倒序:
- 大 小
- 下一页:
- select
- *
- from
- tb1
- where
- nid )
- order by
- nid desc
- limit ;
- select
- *
- from
- tb1
- where
- nid ) A )
- order by
- nid desc
- limit ;
- 上一页:
- select
- *
- from
- tb1
- where
- nid )
- order by
- nid desc
- limit ;
- select
- *
- from
- tb1
- where
- nid ) A
- )
- order by
- nid desc
- limit ;
执行计划
explain + 查询SQL – 用于显示SQL执行信息参数,根据参考信息可以进行SQL优化
- mysql> explain select * from tb2;
- +----+-------------+-------+------+---------------+------+---------+------+------+-------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
- +----+-------------+-------+------+---------------+------+---------+------+------+-------+
- | NULL |
- +----+-------------+-------+------+---------------+------+---------+------+------+-------+
- row in set (0.00 sec)
执行计划
- id
- 查询顺序标识
- 如:mysql) as B;
- +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
- +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
- | NULL |
- | Using where |
- +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
- 特别的:如果使用union连接气值可能为null
- select_type
- 查询类型
- SIMPLE 简单查询
- PRIMARY 最外层查询
- SUBQUERY 映射为子查询
- DERIVED 子查询
- UNION 联合
- UNION RESULT 使用联合的结果
- ...
- table
- 正在访问的表名
- type
- 查询时的访问方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
- ALL 全表扫描,对于数据表从头到尾找一遍
- select * from tb1;
- 特别的:如果有limit限制,则找到之后就不在继续向下扫描
- select * from tb1 where email = 'seven@live.com'
- ;
- 虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。
- INDEX 全索引扫描,对索引从头到尾找一遍
- select nid from tb1;
- RANGE 对索引列进行范围查找
- select * from tb1 where name < 'alex';
- PS:
- between and
- in
- > >= < <= 操作
- 注意:!= 和 > 符号
- INDEX_MERGE 合并索引,使用多个单列索引搜索
- ,,);
- REF 根据索引查找一个或多个值
- select * from tb1 where name = 'seven';
- EQ_REF 连接时使用primary key 或 unique类型
- select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;
- CONST 常量
- 表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。
- ;
- SYSTEM 系统
- 表仅有一行(=系统表)。这是const联接类型的一个特例。
- ) as A;
- possible_keys
- 可能使用的索引
- key
- 真实使用的
- key_len
- MySQL中使用索引字节长度
- rows
- mysql估计为了找到所需的行而要读取的行数 ------ 只是预估值
- extra
- 该列包含MySQL解决查询的详细信息
- “Using index”
- 此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
- “Using where”
- 这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
- “Using temporary”
- 这意味着mysql在对查询结果排序时会使用一个临时表。
- “Using filesort”
- 这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
- “Range checked for each record(index map: N)”
- 这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。
慢日志查询
a、配置MySQL自动记录慢日志
- slow_query_log = OFF 是否开启慢日志记录
- long_query_time 时间限制,超过此时间,则记录
- slow_query_log_file = /usr/slow.log 日志文件
- log_queries_not_using_indexes = OFF 为使用索引的搜索是否记录
注:查看当前配置信息:
show variables like ‘%query%’
修改当前配置:
set global 变量名 = 值
b、查看MySQL慢日志
mysqldumpslow -s at -a /usr/local/var/mysql/MacBook-Pro-3-slow.log
参数详解
- """
- --verbose 版本
- --debug 调试
- --help 帮助
- -v 版本
- -d 调试模式
- -s ORDER 排序方式
- what to sort by (al, at, ar, c, l, r, t), 'at' is default
- al: average lock time
- ar: average rows sent
- at: average query time
- c: count
- l: lock time
- r: rows sent
- t: query time
- -r 反转顺序,默认文件倒序拍。reverse the sort order (largest last instead of first)
- -t NUM 显示前N条just show the top n queries
- -a 不要将SQL中数字转换成N,字符串转换成S。don't abstract all numbers to N and strings to 'S'
- -n NUM abstract numbers with at least n digits within names
- -g PATTERN 正则匹配;grep: only consider stmts that include this string
- -h HOSTNAME mysql机器名或者IP;hostname of db server for *-slow.log filename (can be wildcard),
- default is '*', i.e. match all
- -i NAME name of server instance (if using mysql.server startup script)
- -l 总时间中不减去锁定时间;don't subtract lock time from total time
- """
最全面的 MySQL 索引详解的更多相关文章
- 【详细解析】MySQL索引详解( 索引概念、6大索引类型、key 和 index 的区别、其他索引方式)
[详细解析]MySQL索引详解( 索引概念.6大索引类型.key 和 index 的区别.其他索引方式) MySQL索引的概念: 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分 ...
- 最全面的Android Webview详解
转自:最全面的Android Webview详解 前言 现在很多App里都内置了Web网页(Hyprid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 那么这种该如何实现呢?其实这是 ...
- MySQL 索引详解大全
什么是索引? 1.索引 索引是表的目录,在查找内容之前可以先在目录中查找索引位置,以此快速定位查询数据.对于索引,会保存在额外的文件中. 2. 索引,是数据库中专门用于帮助用户快速查询数据的一种数据结 ...
- mysql索引详解(转)
什么是索引 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里面的 ...
- [转]mysql索引详解
转自:http://www.cnblogs.com/ggjucheng/archive/2012/11/04/2754128.html 什么是索引 索引用来快速地寻找那些具有特定值的记录,所有MySQ ...
- Mysql索引详解及优化(key和index区别)
MySQL索引的概念 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针.更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库 ...
- 11、mysql索引详解
1.索引介绍: 2.建立索引的方法: 注意:索引名称不要相同: (1)在建表的时候,可以增加主键索引的语句如下: 1)例一: create table student1 ( id int(4) not ...
- mysql 索引 详解
索引是快速搜索的关键.MySQL索引的建立对于MySQL的高效运行是很重要的.下面介绍几种常见的MySQL索引类型. 在数据库表中,对字段建立索引可以大大提高查询速度.假如我们创建了一个 mytabl ...
- MySQL 索引详解
本文介绍了数据库索引,及其优.缺点.针对MySQL索引的特点.应用进行了详细的描述.分析了如何避免MySQL无法使用,如何使用EXPLAIN分析查询语句,如何优化MySQL索引的应用. 索引是一种特殊 ...
随机推荐
- kail新手安装
Kali Linux下载链接:http://mirrors.ustc.edu.cn/kali-images/kali-2.0/ (ps:建议用国内镜像源下载,速度有保证) Kali Linux安装之后 ...
- NDK(18)使用C++ STL
1,在Application.mk 中使用 APP_STL := stlport_static 等. APP_ABI := x86 armeabi APP_PLATFORM := android-15 ...
- 【HDOJ】5632 Rikka with Array
1. 题目描述$A[i]$表示二级制表示的$i$的数字之和.求$1 \le i < j \le n$并且$A[i]>A[j]$的$(i,j)$的总对数. 2. 基本思路$n \le 10^ ...
- [POJ2398]Toy Storage(计算几何,二分,判断点在线段的哪一侧)
题目链接:http://poj.org/problem?id=2398 思路RT,和POJ2318一样,就是需要排序,输出也不一样.手工画一下就明白了.注意叉乘的时候a×b是判断a在b的顺时针还是逆时 ...
- 通俗易懂的讲解iphone视图控制器的生命周期
IOS 视图控制器的生命周期非常非常重要,所以我有必要写个文章来和大家一起探讨问题. 今天在学习视图控制器的生命周期,也看了一下网上的一些资料,但总觉得不是那么好理解,首先我们来看一张图: 先粗略讲一 ...
- 面试题_125_to_133_Java 面试中其他各式各样的问题
这部分包含 Java 中关于 XML 的面试题,JDBC 面试题,正则表达式面试题,Java 错误和异常及序列化面试题 125)嵌套静态类与顶级类有什么区别?(答案)一个公共的顶级类的源文件名称与类名 ...
- mkdir -p
git bash 或 mac terminal 我们可以使用 mkdir 命令来创建文件夹. 当前目录创建多个文件夹: $ mkdir a b c 会创建 a .b.c 三个文件夹 但是有时候我们需要 ...
- hdu 4941 Magical Forest ( 双重map )
题目链接 题意: 有一个n*m的田地,里边有k棵树,每棵树的位置为(xi,yi),含有能量值ci.之后又q个询问,分三种; 1)1 a b,将a行和b行交换 2)2 a b,将a列和b列交换 3)3 ...
- ADODB.Connection 错误 '800a0e7a' 未找到提供程序。该程序可能未正确安装。解决方法!
[问题描述]调试基于ACCESS+ASP的网站程序的时候,遇到如下错误: ADODB.Connection 错误 '800a0e7a' 未找到提供程序.该程序可能未正确安装. /Inc/Functio ...
- 關於NPOI的一點補充和示例
最近看到很多人分享NPOI的用法. 但是很多都不是完整示例或者並沒有實戰效果. 剛好最近有個VB.NET的項目有升級原有的oledb select sheet$的做法. 很明顯,NPOI有更好的穩定性 ...