浅谈数据库索引

1.什么是索引

 

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

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

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

建立索引的目的是加快对表中记录的查找或排序。
为表设置索引要付出代价的:一是增加了数据库的存储空间,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。

2.为什么要创建索引

 

创建索引可以大大提高系统的性能。

第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?因为,增加索引也有许多不利的方面。

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

第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

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

3.在哪建索引

 

索引是建立在数据库表中的某些列的上面。在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引:

1.在经常需要搜索的列上,可以加快搜索的速度;

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

3.在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;

4.在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;

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

同样,对于有些列不应该创建索引。一般来说,不应该创建索引的的这些列具有下列特点:
第一,对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

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

第三,对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少,不利于使用索引。

第四,当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改操作远远多于检索操作时,不应该创建索引。

4.索引的数据结构

 

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表:

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL  
  2. );  

 

我们随机向里面插入了10000条记录,其中有一条:5555, admin。

在查找username="admin"的记录 

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. SELECT * FROM mytable WHERE  
  2. username='admin';  

 

时,如果在username上已经建立了索引,MySQL无须任何扫描,即准确可找到该记录。相反,MySQL会扫描所有记录,即要查询10000条记录。

索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索包含多个列。

MySQL索引类型包括:

(1)普通索引

这是最基本的索引,它没有任何限制。它有以下几种创建方式:

◆创建索引

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CREATE INDEX indexName ON mytable(username(length));  

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

 

◆修改表结构

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ALTER mytable ADD INDEX [indexName] ON (username(length))  

 

◆创建表的时候直接指定

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL,  
  2.   
  3. INDEX [indexName] (username(length)) );   

 

删除索引的语法:

 

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. DROP INDEX [indexName] ON mytable;  

 

 

(2)唯一索引

它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:

◆创建索引

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CREATE UNIQUE INDEX indexName ON mytable(username(length))  

 

◆修改表结构

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ALTER mytable ADD UNIQUE [indexName] ON (username(length))  

 

◆创建表的时候直接指定

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL,  
  2. UNIQUE [indexName] (username(length)) );  

 

(3)主键索引

它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL,  
  2. PRIMARY KEY(ID) );   

 

当然也可以用 ALTER 命令。记住:一个表只能有一个主键。

(4)组合索引

为了形象地对比单列索引和组合索引,为表添加多个字段:

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL,  
  2. city VARCHAR(50) NOT NULL, age INT NOT NULL );  

 

为了进一步榨取MySQL的效率,就要考虑建立组合索引。就是将 name, city, age建到一个索引里:

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 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就会用到这个组合索引:

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. SELECT * FROM mytable WHREE username="admin" AND city="郑州" SELECT * FROM  
  2.   
  3. mytable WHREE username="admin"   

 

 

而下面几个则不会用到:

 

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. SELECT * FROM mytable WHREE age=20 AND city="郑州" SELECT * FROM mytable WHREE  
  2. city="郑州"  

 

(5)建立索引的时机

到这里我们已经学会了建立索引,那么我们需要在什么情况下建立索引呢?一般来说,在WHERE和JOIN中出现的列需要建立索引,但也不完全如此,因为MySQL只对<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE才会使用索引。例如:

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. SELECT t.Name FROM mytable t LEFT JOIN mytable m ON t.Name=m.username  
  2. WHERE m.age=20 AND m.city='郑州'  

 

此时就需要对city和age建立索引,由于mytable表的userame也出现在了JOIN子句中,也有对它建立索引的必要。

刚才提到只有某些时候的LIKE才需建立索引。因为在以通配符%和_开头作查询时,MySQL不会使用索引。例如下句会使用索引:

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. SELECT * FROM mytable WHERE username like'admin%'   

 

而下句就不会使用:

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 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%”可以使用索引。

◆不要在列上进行运算

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. select * from users where YEAR(adddate)<2007;  

将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成

 

 

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. select * from users where adddate<‘2007-01-01’;  

 

◆不使用NOT IN和<>操作

原文转载:http://blog.csdn.net/s592652578/article/details/52836559?locationNum=3&fps=1

转载于:https://www.cnblogs.com/Allen0910/p/6744734.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/455931.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iphone屏幕突然变暗_如果你的iPhone屏幕突然变暗,可以这样解决

​​如果在使用 iPhone 的过程中&#xff0c;屏幕忽然变暗&#xff0c;可能有如下原因&#xff1a;开启了“亮度自动调节”功能在 iPhone 中有一项“亮度自动调节”的功能&#xff0c;此功能是根据设备周围的光线条件来调整亮度级别&#xff1a;在光线较暗的地方&#xff0c;传…

宏块与宏块对(附图)

宏块与宏块对&#xff08;附图&#xff09; 假设 A、B 是上下相邻的两个 MB&#xff1a;在非宏块对的情况下&#xff1a;A、B宏块序号不连续&#xff0c;相差图像一行宏块个数。即按光栅扫描顺序编号。在帧宏块对的情况下&#xff1a;A、B宏块序号连续&#xff0c;即按锯齿扫描…

xtrabackup迁移单独一张INNODB表

转载于:https://www.cnblogs.com/llguanli/p/6746130.html

c语言有趣代码_为什么C语言永远不会过时?

直至今天还有人在喊着C语言都过时的语言了&#xff0c;还有什么值得去学的&#xff0c;看现在的python&#xff0c;php等语言现在用起来多简单&#xff0c;谁还去学习老掉牙的C语言&#xff0c;事实真的是这样的吗&#xff1f;笔者作为专门下载了这两种语言的底层源码。由于篇幅…

Pokemon Go将在日本发布 网络安全公司呼吁防范虚假软件

据《每日新闻》报道&#xff0c;手游《Pokemon Go》(精灵宝可梦Go)在海外人气爆棚&#xff0c;日本国内也有望近日发布。日本网络安全公司呼吁&#xff0c;在正式发布前需防范虚假游戏软件。 美国英特尔集团迈克菲公司&#xff08;东京都涩谷区&#xff09;表示&#xff0c;《P…

【接口文档】Django restful framework中自动生成API文档

Django restful framework中自动生成API文档 一、Swagger概述 1.引言 当接口开发完成&#xff0c;紧接着需要编写接口文档。传统的接口文档使用Word编写&#xff0c;or一些接口文档管理平台进行编写&#xff0c;但此类接口文档维护更新比较麻烦&#xff0c;每次接口有变更&am…

【ujson】pip安装ujson报错: error:Microsoft Visual C++ 14.0 is required

在win10上pip安装ujson报错 在使用pip安装依赖包ujson时&#xff0c;遇到了问题&#xff0c;如下&#xff1a; building ujson extension error: Microsoft Visual C 14.0 is required. Get it with "Microsoft Visual C Build Tools": http://landinghub.visua…

CS224n笔记13 卷积神经网络

为什么80%的码农都做不了架构师&#xff1f;>>> 本文由码农场同步&#xff0c;最新版本请查看原文&#xff1a;http://www.hankcs.com/nlp/cs224n-convolutional-neural-networks.html 补充了NLP中相对冷门的CNN&#xff0c;谈了谈调参与发论文的潜规则。从RNN到CN…

android tcp socket框架_socket网络编程知识梳理,让你学会造轮子的能力

在前面几篇中&#xff0c;我给大家介绍了socket的相关知识&#xff0c;也给出了详细的代码&#xff0c;从socket的基本介绍&#xff0c;到IO多路复用&#xff0c;以及粘包拆包&#xff0c;最后到心跳包问题。总的来说大概都把socket网络编程中能碰见的问题都讲了&#xff0c;但…

264分析两大利器:264VISA和Elecard StreamEye Tools

学了264有将近3个月有余&#xff0c;好多时候都在学习老毕的书和反复看JM86的代码&#xff0c;最近才找到264分析两大利器&#xff1a;264VISA和Elecard StreamEye Tools。不由得感叹&#xff0c;恨不逢同时。 简单的说下这两个软件&#xff1a; 264visa 强力的h264实时分析工具…

【解决】Django错误(1146,Table 'xxxx.django_session' doesn't exist)

报错 解决办法&#xff0c;settings.py中取消这行注释&#xff0c;讲session放缓存中 没执行迁移的话&#xff0c;可能是debugtoolbar 把内容存储在session中了 session最后也是放在redis里面的

QTP提供的编程接口实现对QTP操作

我们可以通过调用 Automation Object Model 里的对象接口 ,来实现对QTP 的操作,如打开 /运行脚本等动作Automation object model 的对象结构图如下 (摘自QTP 参考手册 )最新内容请见作者的GitHub页&#xff1a;http://qaseven.github.io/

正态性检验ks和sw区别_非参数检验思路总结,清晰理解就靠它了!

1. 何时使用非参数检验或许你还没有理解什么是参数检验、非参数检验&#xff0c;但一定曾在无意之中使用过它们。如我们常用的方差分析、T检验&#xff0c;都属于参数检验。参数检验&#xff0c;就是假定数据服从某种分布&#xff0c;通过样本信息对总体参数进行检验。因而在分…

【Python基础入门系列】第01天:环境搭建

其实 Python 已经是一个很老的编程语言了&#xff0c;到现在&#xff08;2019年&#xff09; Python 已经高龄 28 岁&#xff0c;比很多程序员的年龄都大。现在之所以这么流行和社区、人工智能的发展&#xff0c;有很大的关系。 千里之行始于足下&#xff0c;今天我们先来学习…

PyCharm的安装以及破解

PyCharm PyCharm是一种Python IDE&#xff0c;带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具&#xff0c;比如调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制。此外&#xff0c;该IDE提供了一些高级功能&#xff0c;以用于…

注解(一)- 基础知识与运行时注解

在java和android 中&#xff0c;注解的运用非常广泛&#xff0c;很多的类库&#xff0c;第三方框架中都用到了注解。所以我们有必要来熟悉注解的相关知识。 Annotation&#xff0c;注解&#xff08;也称为元数据&#xff09;&#xff0c;可以为我们在代码中添加额外的信息&…

【Python基础入门系列】第02天:Python 基础语法

Python 语言与 Perl&#xff0c;C 和 Java 等语言有许多相似之处。但是&#xff0c;也存在一些差异。在本章中我们将来学习 Python 的基础语法&#xff0c;让你快速学会Python 编程。 开始你的第一个 Python 程序 Python 标识符 在 Python 里&#xff0c;标识符由字母、数字、…

如何理解操作系统的不确定性_温度最低-273度,最高却能有1.4亿亿亿亿度,如何定义的?...

地球绕太阳公转&#xff0c;太阳直射点在南北回归线之间往复的移动&#xff0c;也让地球上出现了一年四季的变化冷热交替&#xff0c;对于温度我们有最直观的感受冷暖自知&#xff0c;但仅限于很小的温度范围&#xff0c;在中国东北地区冬天最低温度可以低于零下30摄氏度&#…

不再单打独斗?中国移动联合多企业组建医疗数据公司

中国移动 6月20日消息&#xff0c;中国移动通信集团公司与浪潮集团有限公司作为发起方&#xff0c;共同组建中国健康医疗大数据股份有限公司&#xff0c;在中国移动总部举行投资意向签约仪式。 国家卫生和计划生育委员会副主任金小桃,国务院国有资产监督管理委员会副主任徐福顺…

【Python基础入门系列】第03天:Python 变量与数据类型

这篇文章我们学习 Python 变量与数据类型 Python 变量类型 变量存储在内存中的值。这就意味着在创建变量时会在内存中开辟一个空间。 基于变量的数据类型&#xff0c;解释器会分配指定内存&#xff0c;并决定什么数据可以被存储在内存中。 因此&#xff0c;变量可以指定不同…