数据库索引问题

简单谈谈数据库索引

 

  最近笔试面试特别多的都问到了数据库索引,因为以前并无单独作系统的复习,致使许多关于索引的知识点记忆的很模糊,今天整理下相关笔记(并无深挖,对于初学者仍是能够看看的),仅供参考。mysql

什么是索引

  数据库索引比如是一本书前面的目录,能加快数据库的查询速度。面试

例如这样一个查询:select * from table1 where id=44。若是没有索引,必须遍历整个表,直到ID等于44的这一行被找到为止;有了索引以后(必须是在ID这一列上创建的索引),直接在索引里面找 44(也就是在ID这一列找),就能够得知这一行的位置,也就是找到了这一行。可见,索引是用来定位的。sql

索引分为聚簇索引和非聚簇索引两种,聚簇索引 是按照数据存放的物理位置为顺序的,而非聚簇索引就不同了;聚簇索引能提升多行检索的速度,而非聚簇索引对于单行的检索很快。数据库

  创建索引的目的是加快对表中记录的查找或排序。数据结构

  为表设置索引要付出代价的:一是增长了数据库的存储空间,二是在插入和修改数据时要花费较多的时间(由于索引也要随之变更)。数据库设计

为何要建立索引

建立索引能够大大提升系统的性能。post

第一,经过建立惟一性索引,能够保证数据库表中每一行数据的惟一性。性能

第二,能够大大加快数据的检索速度,这也是建立索引的最主要的缘由。大数据

第三,能够加速表和表之间的链接,特别是在实现数据的参考完整性方面特别有意义。优化

第四,在使用分组和排序子句进行数据检索时,一样能够显著减小查询中分组和排序的时间。

第五,经过使用索引,能够在查询的过程当中,使用优化隐藏器,提升系统的性能。

也许会有人要问:增长索引有如此多的优势,为何不对表中的每个列建立一个索引呢?由于,增长索引也有许多不利的方面。

第一,建立索引和维护索引要耗费时间,这种时间随着数据量的增长而增长。

第二,索引须要占物理空间,除了数据表占数据空间以外,每个索引还要占必定的物理空间,若是要创建聚簇索引,那么须要的空间就会更大。

第三,当对表中的数据进行增长、删除和修改的时候,索引也要动态的维护,这样就下降了数据的维护速度。

在哪建索引

  索引是创建在数据库表中的某些列的上面。在建立索引的时候,应该考虑在哪些列上能够建立索引,在哪些列上不能建立索引。通常来讲,应该在这些列上建立索引:

1.在常常须要搜索的列上,能够加快搜索的速度;

2.在做为主键的列上,强制该列的惟一性和组织表中数据的排列结构;

3.在常常用在链接的列上,这些列主要是一些外键,能够加快链接的速度;在常常须要根据范围进行搜索的列上建立索引,由于索引已经排序,其指定的范围是连续的;

4.在常常须要排序的列上建立索引,由于索引已经排序,这样查询能够利用索引的排序,加快排序查询时间;

5.在常用在WHERE子句中的列上面建立索引,加快条件的判断速度。

一样,对于有些列不该该建立索引。通常来讲,不该该建立索引的的这些列具备下列特色:

第一,对于那些在查询中不多使用或者参考的列不该该建立索引。这是由于,既然这些列不多使用到,所以有索引或者无索引,并不能提升查询速度。相反,因为增长了索引,反而下降了系统的维护速度和增大了空间需求。

第二,对于那些只有不多数据值的列也不该该增长索引。这是由于,因为这些列的取值不多,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即须要在表中搜索的数据行的比例很大。增长索引,并不能明显加快检索速度。

第三,对于那些定义为text, image和bit数据类型的列不该该增长索引。这是由于,这些列的数据量要么至关大,要么取值不多,不利于使用索引。

第四,当修改性能远远大于检索性能时,不该该建立索引。这是由于,修改性能和检索性能是互相矛盾的。当增长索引时,会提升检索性能,可是会下降修改性能。当减小索引时,会提升修改性能,下降检索性能。所以,当修改操做远远多于检索操做时,不该该建立索引。

索引的数据结构

  B-tree,B是balance,通常用于数据库的索引。使用B-tree结构能够显著减小定位记录时所经历的中间过程,从而加快存取速度。而B+tree是B-tree的一个变种,大名鼎鼎的MySQL就广泛使用B+tree实现其索引结构。

  插入(insert)操做:插入一个元素时,首先在B-tree中是否存在,若是不存在,即在叶子结点处结束,而后在叶子结点中插入该新的元素,注意:若是叶子结点空间足够,这里须要向右移动该叶子结点中大于新插入关键字的元素,若是空间满了以至没有足够的空间去添加新的元素,则将该结点进行“分裂”,将一半数量的关键字元素分裂到新的其相邻右结点中,中间关键字元素上移到父结点中(固然,若是父结点空间满了,也一样须要“分裂”操做),并且当结点中关键元素向右移动了,相关的指针也须要向右移。若是在根结点插入新元素,空间满了,则进行分裂操做,这样原来的根结点中的中间关键字元素向上移动到新的根结点中,所以致使树的高度增长一层。

  删除(delete)操做:首先查找B-tree中需删除的元素,若是该元素在B-tree中存在,则将该元素在其结点中进行删除,若是删除该元素后,首先判断该元素是否有左右孩子结点,若是有,则上移孩子结点中的某相近元素到父节点中,而后是移动以后的状况;若是没有,直接删除后,移动以后的状况.。删除元素,移动相应元素以后,若是某结点中元素数目小于ceil(m/2)-1,则须要看其某相邻兄弟结点是否丰满(结点中元素个数大于ceil(m/2)-1),若是丰满,则向父节点借一个元素来知足条件;若是其相邻兄弟都刚脱贫,即借了以后其结点数目小于ceil(m/2)-1,则该结点与其相邻的某一兄弟结点进行“合并”成一个结点,以此来知足条件。

下面结合例子详细讲解mysql中索引的使用

索引是快速搜索的关键。MySQL索引的创建对于MySQL的高效运行是很重要的。下面介绍几种常见的MySQL索引类型。在数据库表中,对字段创建索引能够大大提升查询速度。假如咱们建立了一个 mytable表:CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL ); 咱们随机向里面插入了10000条记录,其中有一条:5555, admin。在查找username="admin"的记录 SELECT * FROM mytable WHERE username='admin';时,若是在username上已经创建了索引,MySQL无须任何扫描,即准确可找到该记录。相反,MySQL会扫描全部记录,即要查询10000条记录。索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表能够有多个单列索引,但这不是组合索引。组合索引,即一个索包含多个列。MySQL索引类型包括:(1)普通索引这是最基本的索引,它没有任何限制。它有如下几种建立方式:◆建立索引CREATE INDEX indexName ON mytable(username(length)); 若是是CHAR,VARCHAR类型,length能够小于字段实际长度;若是是BLOB和TEXT类型,必须指定 length,下同。◆修改表结构ALTER mytable ADD INDEX [indexName] ON (username(length))◆建立表的时候直接指定CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX [indexName] (username(length)) ); 删除索引的语法:DROP INDEX [indexName] ON mytable;(2)惟一索引它与前面的普通索引相似,不一样的就是:索引列的值必须惟一,但容许有空值。若是是组合索引,则列值的组合必须惟一。它有如下几种建立方式:◆建立索引CREATE UNIQUE INDEX indexName ON mytable(username(length))◆修改表结构ALTER mytable ADD UNIQUE [indexName] ON (username(length))◆建立表的时候直接指定CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, UNIQUE [indexName] (username(length)) ); (3)主键索引它是一种特殊的惟一索引,不容许有空值。通常是在建表的时候同时建立主键索引:CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) ); 固然也能够用 ALTER 命令。记住:一个表只能有一个主键。(4)组合索引为了形象地对比单列索引和组合索引,为表添加多个字段:CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, city VARCHAR(50) NOT NULL, age INT NOT NULL ); 为了进一步榨取MySQL的效率,就要考虑创建组合索引。就是将 name, city, age建到一个索引里:ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age); 建表时,usernname长度为 16,这里用 10。这是由于通常状况下名字的长度不会超过10,这样会加速索引查询速度,还会减小索引文件的大小,提升INSERT的更新速度。若是分别在 usernname,city,age上创建单列索引,让该表有3个单列索引,查询时和上述的组合索引效率也会大不同,远远低于咱们的组合索引。虽然此时有了三个索引,但MySQL只能用到其中的那个它认为彷佛是最有效率的单列索引。创建这样的组合索引,实际上是至关于分别创建了下面三组组合索引:usernname,city,age usernname,city usernname 为何没有 city,age这样的组合索引呢?这是由于MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并非只要包含这三列的查询都会用到该组合索引,下面的几个SQL就会用到这个组合索引:SELECT * FROM mytable WHREE username="admin" AND city="郑州" SELECT * FROM mytable WHREE username="admin" 而下面几个则不会用到:SELECT * FROM mytable WHREE age=20 AND city="郑州" SELECT * FROM mytable WHREE city="郑州"(5)创建索引的时机到这里咱们已经学会了创建索引,那么咱们须要在什么状况下创建索引呢?通常来讲,在WHERE和JOIN中出现的列须要创建索引,但也不彻底如此,由于MySQL只对<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE才会使用索引。例如:SELECT t.Name FROM mytable t LEFT JOIN mytable m ON t.Name=m.username WHERE m.age=20 AND m.city='郑州' 此时就须要对city和age创建索引,因为mytable表的userame也出如今了JOIN子句中,也有对它创建索引的必要。刚才提到只有某些时候的LIKE才需创建索引。由于在以通配符%和_开头做查询时,MySQL不会使用索引。例以下句会使用索引:SELECT * FROM mytable WHERE username like'admin%' 而下句就不会使用:SELECT * FROM mytable WHEREt Name like'%admin' 所以,在使用LIKE时应注意以上的区别。(6)索引的不足之处上面都在说使用索引的好处,但过多的使用索引将会形成滥用。所以索引也会有它的缺点:◆虽然索引大大提升了查询速度,同时却会下降更新表的速度,如对表进行INSERT、UPDATE和DELETE。由于更新表时,MySQL不只要保存数据,还要保存一下索引文件。◆创建索引会占用磁盘空间的索引文件。通常状况这个问题不太严重,但若是你在一个大表上建立了多种组合索引,索引文件的会膨胀很快。索引只是提升效率的一个因素,若是你的MySQL有大数据量的表,就须要花时间研究创建最优秀的索引,或优化查询语句。(7)使用索引的注意事项使用索引时,有如下一些技巧和注意事项:◆索引不会包含有NULL值的列只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。因此咱们在数据库设计时不要让字段的默认值为NULL。◆使用短索引对串列进行索引,若是可能应该指定一个前缀长度。例如,若是有一个CHAR(255)的列,若是在前10个或20个字符内,多数值是唯一的,那么就不要对整个列进行索引。短索引不只能够提升查询速度并且能够节省磁盘空间和I/O操做。◆索引列排序MySQL查询只使用一个索引,所以若是where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。所以数据库默认排序能够符合要求的状况下不要使用排序操做;尽可能不要包含多个列的排序,若是须要最好给这些列建立复合索引。◆like语句操做通常状况下不鼓励使用like操做,若是非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可使用索引。◆不要在列上进行运算select * from users where YEAR(adddate)<2007; 将在每一个行上进行运算,这将致使索引失效而进行全表扫描,所以咱们能够改为select * from users where adddate<‘2007-01-01’; ◆不使用NOT IN和<>操做以上,就对其中MySQL索引类型进行了介绍。

相关文章
相关标签/搜索