一、什么是索引

  一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重。

  在数据量和访问量不大的情况下,mysql访问是非常快的,是否加索引对访问影响不大。但是当数据量和访问量剧增的时候,就会发现mysql变慢,甚至down掉,这就必须瑶考虑优化sql了,给数据库建立正确合理的索引,是mysql优化的一个重要手段。

  索引的目的在于提高查询效率,可以类比字典,如果要查“mysql”这个单词,我们肯定需要定位到m字母,然后从下往下找到y字母,再找到剩下的sql。如果没有索引,那么你可能需要把所有单词看一遍才能找到你想要的。除了词典,生活中随处可见索引的例子,如火车站的车次表、图书的目录等。它们的原理都是一样的,通过不断的缩小想要获得数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是我们总是通过同一种查找方式来锁定数据。

  在创建索引时,需要考虑哪些列会用于 SQL 查询,然后为这些列创建一个或多个索引。事实上,索引也是一种表,保存着主键或索引字段,以及一个能将每个记录指向实际表的指针。数据库用户是看不到索引的,它们只是用来加速查询的。数据库搜索引擎使用索引来快速定位记录。

  INSERT 与 UPDATE 语句在拥有索引的表中执行会花费更多的时间,而SELECT 语句却会执行得更快。这是因为,在进行插入或更新时,数据库也需要插入或更新索引值。

二.索引的创建、删除

索引的类型:

1、单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引。 这里不要搞混淆了。

  1.1、普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。

  1.2、唯一索引:索引列中的值必须是唯一的,但是允许为空值,

  1.3、主键索引:是一种特殊的唯一索引,不允许有空值。

2、组合索引:在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。

3、全文索引:全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引,介绍了要求,说说什么是全文索引,就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行,比如有"你是个大煞笔,二货 ..." 通过大煞笔,可能就可以找到该条记录。

4、空间索引:空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。在创建空间索引时,使用SPATIAL关键字。要求,引擎为MyISAM,创建空间索引的列,必须将其声明为NOT NULL。

(1)使用ALTER TABLE语句创建索性

使用于表创建完毕之后再添加。

ALTER TABLE 表名 ADD 索引类型 (unique,primary key,fulltext,index)[索引名](字段名)
//普通索引
alter table table_name add index index_name (column_list) ;
//唯一索引
alter table table_name add unique (column_list) ;
//主键索引
alter table table_name add primary key (column_list) ;

ALTER TABLE可用于创建普通索引、UNIQUE索引和PRIMARY KEY索引3种索引格式,table_name是要增加索引的表名,column_list指出对哪些列进行索引,多列时各列之间用逗号分隔。索引名index_name可选,缺省时,MySQL将根据第一个索引列赋一个名称。另外,ALTER TABLE允许在单个语句中更改多个表,因此可以同时创建多个索引。

(2)使用CREATE INDEX语句对表增加索引

CREATE INDEX可用于对表增加普通索引或UNIQUE索引,可用于建表时创建索引。

CREATE INDEX index_name ON table_name(username(length)); 

如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。

//只能添加这两种索引;
CREATE INDEX index_name ON table_name (column_list)
CREATE UNIQUE INDEX index_name ON table_name (column_list)

table_name、index_name和column_list具有与ALTER TABLE语句中相同的含义,索引名不可选。另外,不能用CREATE INDEX语句创建PRIMARY KEY索引

(3)删除索引

删除索引可以使用ALTER TABLE或DROP INDEX语句来实现。DROP INDEX可以在ALTER TABLE内部作为一条语句处理,其格式如下:

drop index index_name on table_name ;

alter table table_name drop index index_name ;

alter table table_name drop primary key ;

其中,在前面的两条语句中,都删除了table_name中的索引index_name。而在最后一条语句中,只在删除PRIMARY KEY索引中使用,因为一个表只可能有一个PRIMARY KEY索引,因此不需要指定索引名。如果没有创建PRIMARY KEY索引,但表具有一个或多个UNIQUE索引,则MySQL将删除第一个UNIQUE索引。

如果从表中删除某列,则索引会受影响。对于多列组合的索引,如果删除其中的某列,则该列也会从索引中删除。如果删除组成索引的所有列,则整个索引将被删除。

(4) 组合索引与前缀索引

在这里要指出,组合索引和前缀索引是对建立索引技巧的一种称呼,并不是索引的类型。为了更好的表述清楚,建立一个demo表如下。

create table USER_DEMO
(
ID int not null auto_increment comment '主键',
LOGIN_NAME varchar(100) not null comment '登录名',
PASSWORD varchar(100) not null comment '密码',
CITY varchar(30) not null comment '城市',
AGE int not null comment '年龄',
SEX int not null comment '性别(0:女 1:男)',
primary key (ID)
);

为了进一步榨取mysql的效率,就可以考虑建立组合索引,即将LOGIN_NAME,CITY,AGE建到一个索引里:

ALTER TABLE USER_DEMO ADD INDEX name_city_age (LOGIN_NAME(16),CITY,AGE); 

建表时,LOGIN_NAME长度为100,这里用16,是因为一般情况下名字的长度不会超过16,这样会加快索引查询速度,还会减少索引文件的大小,提高INSERT,UPDATE的更新速度。

如果分别给LOGIN_NAME,CITY,AGE建立单列索引,让该表有3个单列索引,查询时和组合索引的效率是大不一样的,甚至远远低于我们的组合索引。虽然此时有三个索引,但mysql只能用到其中的那个它认为似乎是最有效率的单列索引,另外两个是用不到的,也就是说还是一个全表扫描的过程。

建立这样的组合索引,就相当于分别建立如下三种组合索引:

LOGIN_NAME,CITY,AGE
LOGIN_NAME,CITY
LOGIN_NAME

为什么没有CITY,AGE等这样的组合索引呢?这是因为mysql组合索引“最左前缀”的结果。简单的理解就是只从最左边的开始组合,并不是只要包含这三列的查询都会用到该组合索引。也就是说name_city_age(LOGIN_NAME(16),CITY,AGE)从左到右进行索引,如果没有左前索引,mysql不会执行索引查询。

如果索引列长度过长,这种列索引时将会产生很大的索引文件,不便于操作,可以使用前缀索引方式进行索引,前缀索引应该控制在一个合适的点,控制在0.31黄金值即可(大于这个值就可以创建)。

SELECT COUNT(DISTINCT(LEFT(`title`,10)))/COUNT(*) FROM Arctic; -- 这个值大于0.31就可以创建前缀索引,Distinct去重复

ALTER TABLE `user` ADD INDEX `uname`(title(10)); -- 增加前缀索引SQL,将人名的索引建立在10,这样可以减少索引文件大小,加快索引查询速度

三.索引的使用及注意事项

EXPLAIN可以帮助开发人员分析SQL问题,explain显示了mysql如何使用索引来处理select语句以及连接表,可以帮助选择更好的索引和写出更优化的查询语句。

使用方法,在select语句前加上Explain就可以了:

Explain select * from user where id=1;

尽量避免这些不走索引的sql:

SELECT
`sname` FROM `stu` WHERE `age`+10=30;-- 不会使用索引,因为有索引列参与了计算 SELECT `sname` FROM `stu` WHERE LEFT(`date`,4) <1990; --
不会使用索引,因为使用了函数运算,原理与上面相同 SELECT * FROM `houdunwang` WHERE `uname` LIKE'后盾%' -- 走索引 SELECT * FROM `houdunwang` WHERE `uname` LIKE "%后盾%" -- 不走索引 -- 正则表达式不使用索引,这应该很好理解,所以为什么在SQL中很难看到regexp关键字的原因 -- 字符串与数字比较不使用索引;
CREATE TABLE `a` (`a` char(10));
EXPLAIN SELECT * FROM `a` WHERE `a`="1" -- 走索引
EXPLAIN SELECT * FROM `a` WHERE `a`=1 -- 不走索引 select * from dept where dname='xxx' or loc='xx' or deptno=45
--如果条件中有or,即使其中有条件带索引也不会使用。换言之,就是要求使用的所有字段,都必须建立索引, 我们建议大家尽量避免使用or 关键字 -- 如果mysql估计使用全表扫描要比使用索引快,则不使用索引

索引的有点和缺点:

优点:

  • 所有的MySql列类型(字段类型)都可以被索引,也就是可以给任意字段设置索引
  • 大大加快数据的查询速度

缺点:

  • 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT,UPDATE和DELETE。因为更新表时,mysql不仅要保存数据,还要保存一下索引文件
  • 建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在要给大表上建了多种组合索引,索引文件会膨胀很宽

索引只是提高效率的一个方式,如果mysql有大数据量的表,就要花时间研究建立最优的索引,或优化查询语句。

建立索引的几大原则:

  1. 对经常更新的表就避免对其进行过多的索引,对经常用于查询的字段应该创建索引
  2. 数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。
  3. 在一同值少的列上(字段上)不要建立索引,比如在学生表的"性别"字段上只有男,女两个不同值。相反的,在一个字段上不同值较多可是建立索引。
  4. 最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 ,如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
  5. =和in可以乱序,比如a = 1 and b = 2 and c = 3,建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式
  6. 索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) =’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);
  7. 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可

参考:

mysql建立、删除索引及使用

MySQL(五) MySQL中的索引详讲

Mysql学习笔记—索引的更多相关文章

  1. MySQL学习笔记——索引和视图

    索引(index)和管理索引 模式中的一个数据库对象 作用:在数据库中用来加速对表的查询 创建:自动在主键和唯一键上面创建索引 通过使用快速路径访问方法快速定位数据,减少了磁盘的I/O 与表独立存放, ...

  2. 【笔记】MySQL学习之索引

    [笔记]MySQL学习之索引 一 索引简单介绍 索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构.类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可. 普通 ...

  3. MySQL学习笔记一

    MySQL 学习笔记 一 一.数据库简单介绍 1. 按照数据库的发展时间顺序,主要出现了以下类型数据库系统: Ø 网状型数据库 Ø 层次型数据库 Ø 关系型数据库 Ø 面向对象数据库 上面4中数据库系 ...

  4. Mysql学习笔记(二)数据类型 补充

    原文:Mysql学习笔记(二)数据类型 补充 PS:简单的补充一下数据类型里的String类型以及列类型... 学习内容: 1.String类型 2.列类型存储需求 String类型: i.char与 ...

  5. Mysql学习笔记(一)数据类型

    原文:Mysql学习笔记(一)数据类型 学习内容: Mysql基本数据类型. 1.数字类型.. i.整型     Mysql数据类型             含义(有符号)     tinyint(m ...

  6. MySQL学习笔记-锁相关话题

    在事务相关话题中,已经提到事务隔离性依靠锁机制实现的.在本篇中围绕着InnoDB与MyISAM锁机制的不同展开,进而描述锁的实现方式,多种锁的概念,以及死锁产生的原因.   Mysql常用存储引擎的锁 ...

  7. MySQL学习笔记-数据库文件

    数据库文件 MySQL主要文件类型有如下几种 参数文件:my.cnf--MySQL实例启动的时候在哪里可以找到数据库文件,并且指定某些初始化参数,这些参数定义了某种内存结构的大小等设置,还介绍了参数类 ...

  8. MySQL学习笔记-数据库内存

    数据库内存 InnoDB存储引擎内存由以下几个部分组成:缓冲池(buffer pool).重做日志缓冲池(redo log buffer)以及额外的内存池(additional memory pool ...

  9. MySQL学习笔记-cache 与 buffer

    Cache和Buffer是两个不同的概念,简单的说,Cache是加速"读",而 buffer是缓冲"写",前者解决读的问题,保存从磁盘上读出的数据,后者是解决写 ...

随机推荐

  1. Jquery学习笔记(4)--checkbox全选反选

    可能有浏览器兼容性,注意html里的checked是一个属性,存在就默认选中. <!DOCTYPE html> <html lang="en"> <h ...

  2. zend studio 10.6.2 设置默认编码为UTF-8

    如果汉化的:窗体-->常规-->工作空间   然后再选择编码格式 如果未汉化:Window->Preferences->General->wookspace   然后再选 ...

  3. markdown完整语法规范3.0+编辑工具介绍

    以下每一种,我都会挑选最常用的一种写法,一切表述只追求简明扼要.想深究,请查看文末链接. 通用写法:符号+空格+内容 1 引用: 单层引用: > 一级引用 多层引用:内层符号前的空格必须要 &g ...

  4. 【理财】阅读:Millionaire Teacher

    书是本好书,就是翻译的中文书名让人无力吐槽了,叫<拿工薪,三十几岁你也能赚到600万>,浓浓的畅销书架味道有木有. 这本书作者极力推崇指数基金,以及全球极简投资配置策略.重点梳理了一下: ...

  5. Linux系统常用工具集

    整理Linux系统下一些日常工作中常用工具,旨在提高效率: 1.截图软件Shutter 2.通讯聊天工具pidgin 3.守护进程工具daemontools 4.远程桌面服务TigerVNC 5.Ma ...

  6. 【Raspberry pi】GPIO使用指南

    http://www.cnblogs.com/qtsharp/archive/2013/02/28/2936800.html 树莓派RaspberryPi的RPi.GPIO使用指南   Python操 ...

  7. sql查询某个字段最长的记录

    select `字段`, length(`字段`) from 表名 where length(`字段`) = ( select max(length(`字段`)) from 表名  )

  8. iOS-地图开发 Plist文件设置权限

    解决办法: 在.Plist文件中添加 <key>NSLocationUsageDescription</key> <string>请点击“好”以允许访问. 若不允许 ...

  9. IOS控件:长度单位换算(UITextField,IBAction,委托事件touchesBegan)

    #import <UIKit/UIKit.h> @interface demo7_dayViewController : UIViewController { IBOutlet UITex ...

  10. 1.0_搭建PHP服务器环境的步骤

    a,下载安装一款静态web服务器,ex:HTTPD,IIS; b,下载安装PHP引擎: c,在静态服务器配置一下,声明PHP引擎的存在. 注意,以上三步可以用xampp套件来完成. 启动Apache, ...