建索引的原则-以innodb为例

标签: 索引 原则 innodb | 发表时间:2015-08-16 20:01 | 作者:jirongzi_cs2011
出处:http://blog.csdn.net

一、写在前面      

随着开发、测试任务进入尾声,大家都在整理一些项目发布前的一些准备工作,其中一个重要的工作就是为之前写的一些sql语句建立索引,这高并发、高访问量的环境下是非常有必要的,建立一个好的索引能够极大地提高sql语句的查询效率,那么问题来了,到底什么是索引,怎样才能建立一个好的索引呢?本文以mysql Innodb存储引擎为例,结合实际的项目来看一下,如何建立一个好的而索引。

 

二、索引定义

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。

我们知道,数据库查询是数据库的最主要功能之一,例如下面的SQL语句:

SELECT * FROMtest_table WHERE id = 99 ;可以从表test_table中获得id为99的数据记录。

我们都希望查询数据的速度能尽可能的快,因此数据库系统的设计者会从查询算法的角度进行优化。最基本的查询算法当然是顺序查找(linear search),遍历test_table然后逐行匹配id的值是否是99,这种复杂度为O(n)的算法在数据量很大时显然是糟糕的,好在计算机科学的发展提供了很多更优秀的查找算法,例如二分查找(binary search)、二叉树查找(binary tree search)等。如果稍微分析一下会发现,每种查找算法都只能应用于特定的数据结构之上,例如二分查找要求被检索数据有序,而二叉树查找只能应用于二叉查找树上,但是数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不可能同时将两列都按顺序进行组织),所以,在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

举上面的例子主要是为了简单说明地说明索引的作用,包括mysql Innodb在内的大部分数据库系统及文件系统并没有选择二叉树结构作为索引,而是采用了B-Tree或其变种B+Tree作为索引结构,这种索引结构可以最大限度地减少查找过程中磁盘I/O的存取次数,关于什么是B-Tree或B+Tree以及选择它们做数据库索引结构的原因,大家可以自行去学习。下面我们首先介绍下mysql Innodb引擎的两种B+Tree索引。

 

三、MysqlInnodb B+Tree索引

1.一种是主键索引,主键索引即聚集索引(Cluster Index),它不仅有主键,而且有主键所属的全部数据,所以在Innodb中,主键索引即数据;


2.一种是列值为Key,主键位置为Value即 (列值, 主键位置) 的非主键索引(SecondaryIndex)

 

Innodb属于索引组织表,所有的数据全部挂在主键叶子节点下。所以如果不能保证主键的插入顺序,那么会发生大量的主键节点分裂,产生大量的I/O操作。另外Innodb规定单个索引字段的长度不得超过768字节,否则截断超出长度不放入索引。

Innodb的非主键索引全部都指向主键索引,查找非主键索引无法获得整行数据,需要通过叶子节点的指针查到其主键索引的位置才能获得整行数据,所以主键索引必须设计得尽可能小,否则非主键索引将会非常的大。

 

四、建立索引的原则:

下面我们看一下建立一个好的索引需要遵循的原则,并结合具体的例子来做说明;

1.最左前缀匹配原则,非常重要的原则,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的顺序可以任意调整。

2.=和in可以乱序,比如a = 1and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。

3.尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录

4.索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ‘2015-08-14’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(‘2015-08-14’)。

5.尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

6.在order by或者group by子句中,如果想通过索引来进行排序,所建索引列的顺序必须与order by或者group by子句的顺序一致,并且所有列的排序方向(倒序或者正序)都一样;如果查询关联多张表,则只有order by子句引用的字段全部来自第一张表时,才能利用索引来排序;order by或者group by语句与查询型语句的限制是一样的:需要满足索引的最左前缀原则;否则mysql就要执行排序操作,无法利用索引来排序;(有一种情况order by或者group by子句可以不满足最左前缀原则,就是其前导为常量的时候,如果where或者join对这些列指定了常量,就可以弥补索引的不足)。

 

五、举例

语句1:


语句2:


对于这两条语句,如果单独进行考虑的话,大家可能会建立两个索引,针对语句1建立(status,netting_batch_no,debtor_agent_member_id),针对语句2建立(netting_batch_no,debtor_agent_member_id,transaction_currency);如果综合考虑来看的话,其实一个索引就够了,即(netting_batch_no,debtor_agent_member_id),这里没必要将status或者transaction_currency字段放到索引中,因为这两个字段的区分度太差;

根据建立索引的原则2,语句1是可以走到这个索引的;

根据建立索引的原则1,语句2也是可以走到这个索引的;

索引不是越多越好,建立过多的索引会增加数据库内存或者磁盘的消耗,并且会影响到得插入、删除等操作的性能,索引在建立索引时要遵循索引建立的原则,通盘考虑;

作者:jirongzi_cs2011 发表于2015/8/16 12:01:31 原文链接
阅读:75 评论:0 查看评论

相关 [索引 原则 innodb] 推荐:

建索引的原则-以innodb为例

- - CSDN博客推荐文章
随着开发、测试任务进入尾声,大家都在整理一些项目发布前的一些准备工作,其中一个重要的工作就是为之前写的一些sql语句建立索引,这高并发、高访问量的环境下是非常有必要的,建立一个好的索引能够极大地提高sql语句的查询效率,那么问题来了,到底什么是索引,怎样才能建立一个好的索引呢. 本文以mysql Innodb存储引擎为例,结合实际的项目来看一下,如何建立一个好的而索引.

Mysql-innodb-B+索引

- - 掘金后端
这是读书笔记,Mysql,innodb系列一共3篇. Mysql-innodb-B+索引(本篇). Mysql-innodb-锁(预计20200523). Mysql-innodb-事务预计20200530). CREATE TABLE `aid_***_detail` ( //省略所有字段 PRIMARY KEY (`id`), KEY `range_idx` (`range_id`,`is_delete`,`range_detail_num`,`goods_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4复制代码.

MySQL InnoDB B+树索引

- - OurMySQL
B+树索引在DB中有一个特点就是高扇出性,一般在DB中B+树的高度在2-3层左右,也就意味着只需要2-3次的IO操作即可. 而现在的磁盘每秒差不多在100次IO左右,2-3次意味着查询时间只需0.02-0.03秒. InnoDB存储引擎表是索引组织表,即表中数据安装主键顺序存放. 而聚集索引就是按照每张表的主键构造一颗B+,并且叶节点存放着整张表的行记录数据,因此也让聚集索引也是索引的一部分.

Innodb索引和锁的学习笔记

- - 数据库 - ITeye博客
附录:前段时间学习了下innodb锁的相关知识,对锁和事务有了大体理解,这里做个小总结. 1.Innodb事务和锁的关系.    Innodb区别于MyISAM的两个特点就是Innodb对于事务的支持和对行锁的支持. 事务要求了一组SQL语句的ACID特性,同时为了避免对一行记录的并发更新,innodb本身会在一定情况下加锁,然后等语句所在的事务退出后(rollbak或者commit)释放锁.

InnoDB一定会在索引中加上主键吗

- - OurMySQL
DBA群里在讨论一个问题,到底InnoDB会不会在索引末尾加上主键,什么时候会加. 我之前看代码记得是如果索引末尾就是主键,那么InnoDB就不再添加主键了,如果索引末尾不是主键,那么会添加主键,但是这跟测试结果不符:. 插入部分数据后可以看到idx1和idx2两个索引的大小相同. 这说明idx1和idx2的内部结构是一样的,因此 不可能 是idx1在内部存为(a,b,a).

关于InnoDB索引长度限制的tips

- - IT技术博客大学习
有同学问到MySQL数据库InnoDB存储引擎的索引长度问题,简单说几个tips. 大家经常碰到InnoDB单列索引长度不能超过767bytes,实际上联合索引还有一个限制是3072. 可以看到,由于每个字段占用255*3, 因此这个索引的大小是3825>3072,报错. 我们知道InnoDB一个page的默认大小是16k.

Mysql InnoDB锁

- - 数据库 - ITeye博客
抄自:http://www.cnblogs.com/qq78292959/archive/2013/01/30/2882745.html. Mysql常用存储引擎的锁机制. MyISAM和MEMORY采用表级锁(table-level locking). BDB采用页面锁(page-leve locking)或表级锁,默认为页面锁.

[MySQL优化案例]系列 — 索引、提交频率对InnoDB表写入速度的影响

- - MySQL中文网
本次,我们来看看索引、提交频率对InnoDB表写入速度的影响,了解有哪些需要注意的. 1、关于索引对写入速度的影响: a、如果有自增列做主键,相对完全没索引的情况,写入速度约提升 3.11%; b、如果有自增列做主键,并且二级索引,相对完全没索引的情况,写入速度约降低 27.37%;. 因此,InnoDB表最好总是有一个自增列做主键.

Mysql Innodb 引擎优化

- 彦强 - 阿辉的空间
作/译者:吴炳锡,来源:http://imysql.cn/ & http://www.mysqlsupport.cn 转载请注明作/译者和出处,并且不能用于商业用途,违者必究. InnoDB给MySQL提供了具有提交,回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎. InnoDB锁定在行级并且也在SELECT语句提供 一个Oracle风格一致的非锁定读.

Percona XtraBackup InnoDB 備份工具

- - 小惡魔 - 電腦技術 - 工作筆記 - AppleBOY
大家可以選擇透過 yum 或 apt Repository 方式安裝,下面介紹 apt 方式即可. 將 apt 伺服器寫入 /etc/apt/sources.list. VERSION 請至換 Ubuntu Server 版號,如果您想測試實驗性版本請加入底下連結. 根據不同的 MySQL 版本來選擇 XtraBackup 指令,可以參考 Choosing the Right Binary,所以大家不要用錯指令了.