软件开发人员真的了解SQL索引吗(索引使用原则)
前两篇文章我总结了一些SQL数据库索引的问题,这篇主要来分析下索引的优缼点,以及如何正确使用索引。
索引的优点:这个显而易见,正确的索引会大大提高数据查询,对结果进行排序、分组的操作效率。
索引的缺点:优点显而易见,同样缺点也是显而易见:
1:创建索引需要额外的磁盘空间,索引最大一般为表大小的1.2倍左右。
2:在表数据修改时,例如增加,删除,更新,都需要维护索引表,这是需要系统开销的。
3:不合理的索引设计非但不能利于系统,反而会使系统性能下降。例如我们在一个创建有非聚集索引的列上做范围查询,此列的索引不会起到任何的优化效果,反而由于数据的修改而需要维护索引表,从而影响了对数据修改的性能。
实际例子:还是拿前两篇文章的学生表来讲吧,要查询成绩在50分以上的学生信息select * from student where score>50。学生表包含了100000行记录,而且学分是随机生成的,这样从数据量以及数据分布上都有一定的保障。
第一种情况:学生表有索引。
1:存在聚集索引,但聚集索引不在学分上,这里只分析学分不是聚集索引的情况。
(1):学分上没有索引。此时SQL会通过聚集索引来查找数据,这点估计大家都会知道。
(2):学分上有索引。这种情况,SQL会使用上学分上的索引吗?这个问题估计不是每个人都能回答正确的。既然学分上有索引,而where中又有此列,理应使用了索引,但实际情况并没有使用索引。因为出现了范围查找,如果一个索引一个索引的比较,在性能上比起直接按聚集索引查找全部数据后再过滤来的差。那学分上的索引什么时候 SQL会优先考虑呢?当score指定为一个具体值时,就能使用学分索引查找了。从下图的SQL执行计划可以得知。
2:不存在聚集索引。
(1):在学分上没有索引,其它字段有索引,这种情况就会出现表扫描。
(2):在学分上有索引,是否会按照学分上的索引进行查找呢?由于上面的表数据量也不少,一般会认为SQL不会采用表扫描,因为会查找全部记录,但实际情况表明SQL对于范围查询也行采用表扫描而不是按学生索引查询。我们也可以强制SQL按学分查询,于是有下面的SQL执行计划比较,我们可以清楚的看出,强制使用学分做为索引查询比表搜索的性能要差很多。
第二种情况:学生表没有索引。这个情况没有分析的价值。
什么字段不适合创建索引?
1:不经常使用的列,这种索引带来缺点远大于带来的优点。
2:逻辑性的字段,例如性别字段等等,匹配的记录太多,和表扫描比起来不相上下。
3:字段内容特别大的字段,例如text等,这会大大增大索引所占用的空间以及索引更新时的速度。
我们说SQL在维护索引时要消耗系统资源,那么SQL维护索引时究竟消耗了什么资源?会产生哪些问题?究竟怎样才能优化字段的索引?
第一:当数据页达到了8K(数据页最大为8K) 容量,如此时发生插入或更新数据的操作,将导致页的分裂。
1、聚集索引的情况下:聚集索引将被插入和更新的行指向特定的页,该页由聚集索引关键字决定;
2、只有堆的情况下:有空间就可以插入新的行,对行数据的更新需要更多的空间,如果大于了当前页的可用空间,行就被移到新的页中,且在原位置留下一个转发指针,指向被移动的新行,如果具有转发指针的行又被移动了,那么原来的指针将重新指向新的位置;
3、堆中有非聚集索引,尽管插入和更新操作,不会发生页分裂,但非聚集索引上仍然产生页分裂。
总结:无论有无索引,很多数据将保留在老页面,其它将放入新页面,并且新页面可能被分配到任何可用的页,频繁页分裂,表会产生大量数据碎片,直接造成I/O 效率下降。
引出问题:为什么数据库对于varchar最大值设置为8000,而不是10000呢?
答:是由于数据页大小最大为8K。
第二:针对上述索引可能造成的页分页的解决方案,填充因子。
创建索引时,可以为索引指定一个填充因子,在索引的每个叶级页面上保留一定百分比的空间,将来数据可以进行扩充和减少页分裂。值从0到100的百分比数值,100 时表示将数据页填满。不对数据进行更改时(例如只读表中)才用此设置,实用价值不大。值越小则数据页上的空闲空间越大,可以减少在索引增长过程中进行页分裂,但需要占用更多的硬盘空间。填充因子也不能设置过小,过小会影响SQL的读取性能,因为填充因子造成数据页的增多。一般我们公司设置的填充因子是80。
索引是否是一尘不变的?
随着业务的变化,数据的变化,会发生有些索引的用处可能发生变化,例如:
1:原来主要靠用户名搜索记录,现在业务更改为按用户所在城市搜索等等,此时我们需要即时变更表索引以适应新业务的变化,即数据和使用模式发生了大幅度变化。
2:系统上线前不合理的索引,随着数据的增加,缺点越来越明显,此时需要调整索引。
3:随着数据的增加,产生了越来越多的页分裂,导致索引性能越来越低。
上面的几种情况,我们就需要选择重建索引来彻底解决问题。
总结索引使用原则:
1:不要索引数据量不大的表,对于小表来讲,表扫描的成本并不高。
2:不要设置过多的索引,在没有聚集索引的表中,最大可以设置249个非聚集索引,过多的索引首先会带来更大的磁盘空间,而且在数据发生修改时,对索引的维护是特别消耗性能的。
3:合理应用复合索引,有某些情况下可以考虑创建包含所有输出列的覆盖索引。
4:对经常使用范围查询的字段,可能考虑聚集索引。
5:避免对不常用的列,逻辑性列,大字段列创建索引。
有说的不对的地方,欢迎大家指正。
软件开发人员真的了解SQL索引吗(索引使用原则)的更多相关文章
- 程序员眼中的 SQL Server-执行计划教会我如何创建索引?
先说点废话 以前有 DBA 在身边的时候,从来不曾考虑过数据库性能的问题,但是,当一个应用程序从头到脚都由自己完成,而且数据库面对的是接近百万的数据,看着一个页面加载速度像乌龟一样,自己心里真是有种挫 ...
- 程序员眼中的 SQL Server-非聚集索引能给我们带来什么?
写在前面 最近在做的一个项目,页面访问的时候很慢(大概几秒钟的样子),然后用日志记录的方式,来排查这个问题,最后发现是 Entity Framework 初始化的一个坑(大概要花 6-7 秒),详见: ...
- SQL语句-创建索引
语法:CREATE [索引类型] INDEX 索引名称ON 表名(列名)WITH FILLFACTOR = 填充因子值0~100 GO USE 库名GO IF EXISTS (SELECT * FRO ...
- SQL Server 解读【已分区索引的特殊指导原则】(3) - 非聚集索引分区
一.前言 在MSDN上看到一篇关于SQL Server 表分区的文档:已分区索引的特殊指导原则,如果你对表分区没有实战经验的话是比较难理解文档里面描述的意思.这里我就里面的一些概念进行讲解,方便大家的 ...
- SQL Server创建索引(转)
什么是索引 拿汉语字典的目录页(索引)打比方:正如汉语字典中的汉字按页存放一样,SQL Server中的数据记录也是按页存放的,每页容量一般为4K .为了加快查找的速度,汉语字(词)典一般都有按拼音. ...
- SQL索引学习-索引结构
前一阵无意中和同事讨论过一个SQL相关的题(通过一个小问题来学习SQL关联查询),很惭愧一个非常简单的问题由于种种原因居然没有回答正确,数据库知识方面我算不上技术好,谈起SQL知识的学习我得益于200 ...
- SQL Server创建索引
原文:SQL Server创建索引 什么是索引 拿汉语字典的目录页(索引)打比方:正如汉语字典中的汉字按页存放一样,SQL Server中的数据记录也是按页存放的,每页容量一般为4K .为了加快查找的 ...
- (转)SQL Server创建索引
什么是索引拿汉语字典的目录页(索引)打比方:正如汉语字典中的汉字按页存放一样,SQL Server中的数据记录也是按页存放的,每页容量一般为4K .为了加快查找的速度,汉语字(词)典一般都有按拼音.笔 ...
- 公司内部培训SQL Server传统索引结构PPT分享
公司内部培训SQL Server传统索引结构PPT分享 下载地址 http://files.cnblogs.com/files/lyhabc/SQLServer%E4%BC%A0%E7%BB%9F%E ...
随机推荐
- 一起写2048(160行python代码)
前言: Life is short ,you need python. --Bruce Eckel 我与2048的缘,不是缘于一个玩家.而是一次,一次,重新的ACM比赛.四月份校赛初赛,第一次碰到20 ...
- OCEANIAERP对接-code盘点机并存储实时库存计划和方案的使用,实时库存,云清查方案
1. PDA手持设备按键说明 [Tab]键:使输入焦点在控件上切换. [ESC]键:弹出是否退出确认对话框,退出操作界面或程序. [OK]键:确认输入或选择,进入下一步操作. [C]键:删除键 ...
- 接口设计ie常见的问题
问题叙述性说明: 当围绕一个简单的页面布局设计.我发现了一个奇怪的相对布局问题. 同的方式围绕布局接口.它是利用左div浮动.对div设定 margin-left这样达到的效果.实现了chrome浏览 ...
- Java 新特性(5) - Java EE 5 新特性
Java EE 5 由 Java Community Process 通过 Java Specification Request 244 发布,这个 “总纲” JSR 指出了详细描述 Java EE ...
- TCP/IP 网络编程(六)
流程模型: 线程模型: 线程的创建和运行流程 #include <pthread.h> int pthread_create(pthread_t * restrict thread, co ...
- wikioi 1034 家 实时动态的网络流量(费用流)
因为随着时间的推移.网络侧变得,因此,常见的网络流量也解决不了这个问题,.如果T毕竟运输时间. 为此.我们可以基于时间分割点,所有的点将被分割为T点. 对于每一个点,下一次甚至一个容量为本人INF边缘 ...
- HDU4893:Wow! Such Sequence!(段树lazy)
Problem Description Recently, Doge got a funny birthday present from his new friend, Protein Tiger f ...
- ZOJ-3652-Maze(BFS)
Celica is a brave person and believer of a God in the bright side. He always fights against the mons ...
- 安德鲁斯 建立与各种听众自己定义的ScrollView
=== 建立与各种听众自己定义的ScrollView === 尽管安卓5.1已经release, 可是ScrollView的封装和对外API依然少的可怜, 尽管它优化得非常好了. 所以问题来了: Sc ...
- ocp11g培训内部教材_051课堂笔记(047)_SQL
OCP 051课堂笔记 目录 OCP 051课堂笔记... 1 第一章.Oracle命令类别:... 4 第二章.SQL的基本函数... 4 2.1 单行函数与多行函数... 4 2.2 单行函数的几 ...