MySQL索引优化


概述

索引就是为特定的mysql字段进行一些算法排序,比如二叉树算法和哈希算法,哈希算法是通过简历特征值,然后根据特征值来快速查找。MyISAM和InnoDB存储引擎的表默认创建索引都是BTREE索引。MyISAM还支持全文本索引,该索引可以用于创建全文搜索。
不使用索引,MySQL必须从第一条记录开始读完整张表找到相关数据,如果表中查询的列有索引,MySQL就能快速到达下一个位置去搜寻到数据文件中间,而不用查询所有数据,大大提高查询效率。


索引的利弊

索引的好处:

  1. 减少检索过程中需要读取的数据量,提高检索效率,降低数据库IO成本。
  2. 降低数据库的排序成本。因为索引就是对字段数据进行排序后存储的,如果待排序字段和索引字段一致,在取出数据后就不用再次排序了。

索引的弊端:

  1. 索引也是一种数据,随着数据量增大,在建立索引的同时必然会占用大量表空间。
  2. 索引会增加增、删、改操作带来的IO量。

BTree索引

MySQL中使用最频繁的索引类型,基本所有的存储引擎都支持BTree索引,一些引擎在使用BTree索引时也会对存储结构稍作修改,比如MyISAM存储引擎使用的B+Tree。

  • MyISAM引擎索引结构的叶子节点的数据域,存放的并不是数据记录,实际存放的是数据记录的地址。检索时先按照B+Tree的检索算法进行检索,找到关键字,取出对应数据域的数据,作为地址,根据地址找到对应的数据记录。索引文件和数据文件分离,这样的索引被称作非聚簇索引
非聚簇索引
  • InnoDB引擎索引结构的叶子节点的数据域,存放的就是实际的数据,或者说InnoDB的数据文件本身就是主键索引文件,这样的索引被称为聚簇索引

Hash索引

主要是通过Hash算法,将数据库字段数据转换成定长的Hash值,将这条数据的行指针一同存入Hash表的对应位置,当发生Hash碰撞时(即两个不同关键字的Hash值相同),在对应Hash键下以连表形式存储。
在进行查询时,就对待查关键字再次执行相同的Hash算法,得到Hash值,然后到对应的Hash表中取出数据,如果发生Hash碰撞,就需要在取值时进行筛选。

Full-Text索引

MySQL中只有MyISAM支持全文索引,并且只有CHARVARCHARTEXT类型支持。可以通过多字段组合的全文索引一次性模糊匹配多个字段,用于替代效率低下的LIKE模糊匹配操作。


索引类型

UNIQUE唯一索引
不可以出现相同的值,可以有NULL值。

INDEX普通索引
允许出现相同的值。

PRIMARY KEY主键索引
不允许出现相同的值,且不能为NULL值,一个表只能有一个primary_key索引。

fulltext 全文索引
fulltext索引只适用于MyISAM表,同时只支持charvarchartext类型;fulltext索引可用于在一篇文章中检索文本信息,针对较大的数据,全文索引很消耗时间和存储空间。

组合索引
为了更多的提高效率可建立组合索引,遵循最左前缀原则。


创建索引

我们可以在创建表的同时建立索引,也可以单独使用CREATE INDEX或者ALTER TABLE来为表添加索引。

  • CREATE INDEX
    普通索引:CREATE INDEX 'index_name' ON table_name('column')
    唯一索引:CREATE UNIQUE INDEX 'index_name' ON table_name('column')
    不能使用CREATE INDEX语句创建PRIMARY KEY索引

  • ** ALTER TABLE**
    普通索引:ALTER TABLE 'table_name' ADD INDEX index_name('column')
    唯一索引:ALTER TABLE 'table_name' ADD UNIQUE ('column')
    主键索引:ALTER TABLE 'table_name' ADD PRIMARY KEY('column')
    组合索引:ALTER TABLE 'table_name' ADD INDEX index_name('column1','column2','column3')

删除索引

DROP INDEX index_name ON table_name
ALTER TABLE table_name DROP INDEX index_name
这两句是等价的,作用都是删除表table_name中的索引index_name。

删除主键索引只能使用以下方式:
ALTER TABLE table_name DROP PRIMARY KEY

查看索引

使用以下SQL语句查看索引信息:

show index from table_name;

Table:表名。
Non_unique:如果索引不能包括重复值则为0,可以包括重复值则为1。
Key_name:索引名。
Seq_in_index:索引中的序列号。
Column_name:列名。
Collation:列以什么方式存储在索引中,A表示升序,NULL表示无分类。
Cardinality:索引中唯一值数目的估计值。数值越大,进行联合索引时,MySQL使用该索引的机会越大。
Sub_part:如果列被部分编入索引,则为编入索引的字符数,如果整列被编入索引,则为NULL。
Packed:关键字的压缩方式,NULL为没有压缩。
Null:如果列含有NULL,则为YES,相反则为NO。
index_type:用过的索引方法,BTREE、HASH、RTREE、FULLTEXT
Comment:评注。


适合建立索引的地方

  1. 为维度高的列创建索引
    比如表中有a、b、c、d、e、a、c、d、a、b一共10行数据,那么这张表的维度为5,不重复值出现的个数越多,维度越高。性别这种就不适合建立索引。
  2. 对join、where、on、order by、group by中出现的列使用索引
  3. 为较长的字符串使用前缀索引
  4. 使用组合索引可以减少文件索引大小,速度优于多个单列索引

不适合建立索引的地方

  1. 表记录太少,就几条数据
  2. 经常进行插入、删除、修改操作的表
  3. 数据重复且分布平均的字段,比如性别
  4. 唯一性太差的字段,即使频繁作为查询条件

使用索引注意

一般来说在where和join中出现的列需要建立索引,但也不完全是,因为MySQL只对<、<=、=、>、>=、between、in和部分情况下的like才会使用索引。

  • 不要在列上进行计算
SELECT 'name' FROM 'stu' WHERE 'age'+10=30;       //不会使用索引,因为所有索引列参与了计算 
SELECT 'sname' FROM 'stu' WHERE LEFT('date',4) <1995;  //不会使用索引,因为使用了函数运算
  • 注意like语句操作
SELECT * FROM 'stu' WHERE 'name' LIKE '李%'         //走索引 
SELECT * FROM 'stu' WHERE 'name' LIKE "%李%"         // 不走索引 
  • 字符串与数字比较不使用索引。
CREATE TABLE 'a' ('a' char(10)); 
EXPLAIN SELECT \* FROM 'a' WHERE 'a'="1"   //走索引 
EXPLAIN SELECT \* FROM 'a' WHERE 'a'=1    // 不走索引 
  • 避免使用or
//如果条件中有or,即使其中有条件带索引也不会使用。换言之,就是要求使用的所有字段,都必须建立索引, 尽量避免使用or 关键字 。
SELECT\* FROM 'stu' WHERE name='xxx' or class='xx' or age=18  
  • 正则表达式不使用索引。
  • 使用短索引
    对字符串列今夕索引,尽量指定一个前缀长度,如,一个列CHAR(255),前面的10个字符多数值是唯一的,就不要对整个列进行索引,短索引可以提高查询速度并节省存储空间。
  • 索引中不要包含NULL
    只要列中有NULL值就都不会被包含在索引中,复合索引中只要有一列包含NULL值,此列对复合索引就是无效的;在建立数据库库时就避免让字段默认值为NULL。
  • 如果mysql估计使用全表扫描要比使用索引快,则不使用索引。

前缀索引
PS:前缀索引是对索引技巧的一种称呼,并非索引类型。
如果我们的索引列过长,就会产生很大的索引文件,可以使用前缀索引的方式进行索引,前缀索引应该控制在一个合适的点:
SELECT COUNT(DISTINCT(LEFT(\title`,10))) / COUNT(*) FROM Arctic; `
当计算出的值大于0.31黄金值时即可创建.

增加前缀索引:
ALTER TABLE \user` ADD INDEX `uname`(title(10));`
将用户名的索引建立在10,这样可以减小索引文件,提示索引速度。


参考:http://lib.csdn.net/article/mysql/44988


施工ing 2017-5-4

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容

  • 命名规则:表名_字段名 1、需要加索引的字段,要在where条件中 2、数据量少的字段不需要加索引 3、如果whe...
    Dg_fc58阅读 704评论 0 50
  • 本文主要讨论MySQL索引的部分知识。将会从MySQL索引基础、索引优化实战和数据库索引背后的数据结构三部分相关内...
    java欧阳丰阅读 590评论 0 2
  • “池塘边的榕树上有一群知了在叫着夏天”伴随着熟悉的音乐声,夏天也悄悄地来临了。 记得小时侯,夏天的代名词就...
    biblli阅读 202评论 0 1
  • 今天是什么日子 起床:8:30 ,睁开眼不再睡了,算起床吧。 就寝:11:30 天气:晴朗加多云 心情:还好,未复...
    小孬蛋儿阅读 150评论 0 1
  • 多年来一直陪读,一直被深深的折磨着,身心俱疲。最近看到一句话:育儿即育己。想想也对,顿时觉得应该心平气和的继续参与...
    九五自尊阅读 421评论 0 1