索引是与表或视图关联的磁盘上结构,能够加快从表或视图中检索行的速度。索引包含由表或视图中的一列或多列生成的键。这些键存储在一个结构(B 树)中,使 SQL Server 能够快速有效地查找与键值关联的行。
表或视图能够包含如下类型的索引:
* 汇集
o 汇集索引根据数据行的键值在表或视图中排序和存储这些数据行。索引定义中包含汇集索引列。每一个表只能有一个汇集索引,由于数据行自己只能按一个顺序排序。
o 只有当表包含汇集索引时,表中的数据行才按排序顺序存储。若是表具备汇集索引,则该表称为汇集表。若是表没有汇集索引,则其数据行存储在一个称为堆的无序结构中。
* 非汇集
o 非汇集索引具备独立于数据行的结构。非汇集索引包含非汇集索引键值,而且每一个键值项都有指向包含该键值的数据行的指针。
o 从非汇集索引中的索引行指向数据行的指针称为行定位器。行定位器的结构取决于数据页是存储在堆中仍是汇集表中。对于堆,行定位器是指向行的指针。对于汇集表,行定位器是汇集索引键。
o 您能够向非汇集索引的叶级添加非键列以跳过现有的索引键限制(900 字节和 16 键列),并执行完整范围内的索引查询。
汇集索引和非汇集索引均可以是惟一的。这意味着任何两行都不能有相同的索引键值。另外,索引也能够不是惟一的,即多行能够共享同一键值。
每当修改了表数据后,都会自动维护表或视图的索引。
索引和约束
对表列定义了 PRIMARY KEY 约束和 UNIQUE 约束时,会自动建立索引。例如,若是建立了表并将一个特定列标识为主键,则 数据库引擎自动对该列建立 PRIMARY KEY 约束和索引。有关详细信息,请参阅建立索引(数据库引擎)。
2、索引有什么用
与书中的索引同样,数据库中的索引使您能够快速找到表或索引视图中的特定信息。索引包含从表或视图中一个或多个列生成的键,以及映射到指定数据的存储位置的指针。经过建立设计良好的索引以支持查询,能够显著提升数据库查询和应用程序的性能。索引能够减小为返回查询结果集而必须读取的数据量。索引还能够强制表中的行具备惟一性,从而确保表数据的数据完整性。
设计良好的索引能够减小磁盘 I/O 操做,而且消耗的系统资源也较少,从而能够提升查询性能。对于包含 SELECT、UPDATE、DELETE 或 MERGE 语句的各类查询,索引会颇有用。例如,在 AdventureWorks 数据库中执行的查询 SELECT Title, HireDate FROM HumanResources.Employee WHERE EmployeeID = 250。执行此查询时,查询优化器评估可用于检索数据的每一个方法,而后选择最有效的方法。可能采用的方法包括扫描表和扫描一个或多个索引(若是有)。
扫描表时,查询优化器读取表中的全部行,并提取知足查询条件的行。扫描表会有许多磁盘 I/O 操做,并占用大量资源。可是,若是查询的结果集是占表中较高百分比的行,扫描表会是最为有效的方法。
查询优化器使用索引时,搜索索引键列,查找到查询所需行的存储位置,而后从该位置提取匹配行。一般,搜索索引比搜索表要快不少,由于索引与表不一样,通常每行包含的列很是少,且行遵循排序顺序。
查询优化器在执行查询时一般会选择最有效的方法。但若是没有索引,则查询优化器必须扫描表。您的任务是设计并建立最适合您的环境的索引,以便查询优化器能够从多个有效的索引中选择。SQL Server 提供的数据库引擎优化顾问能够帮助分析数据库环境并选择适当的索引。
3、索引怎么用
索引其实关键目的是为了加快检索速度而创建的,因此,怎么用索引是数据库系统自己的事情,做为数据库设计或使用者,设计并建立好索引而后体验加上索引后的查询变快的感受就好了。因此,索引怎么用就变为了“怎么建立合适的索引”,如下说明这个问题:
索引设计不佳和缺乏索引是提升数据库和应用程序性能的主要障碍。设计高效的索引对于得到良好的数据库和应用程序性能极为重要。为数据库及其工做负荷选择正确的索引是一项须要在查询速度与更新所需开销之间取得平衡的复杂任务。若是索引较窄,或者说索引关键字中只有不多的几列,则须要的磁盘空间和维护开销都较少。而另外一方面,宽索引可覆盖更多的查询。您可能须要试验若干不一样的设计,才能找到最有效的索引。能够添加、修改和删除索引而不影响数据库架构或应用程序设计。所以,应试验多个不一样的索引而无需犹豫。
SQL Server 中的查询优化器可在大多数状况下可靠地选择最高效的索引。整体索引设计策略应为查询优化器提供可供选择的多个索引,并依赖查询优化器作出正确的决定。这在多种状况下可减小分析时间并得到良好的性能。若要查看查询优化器对特定查询使用的索引,请在 SQL Server Management Studio 中的“查询”菜单上选择“包括实际的执行计划”。
不要老是将索引的使用等同于良好的性能,或者将良好的性能等同于索引的高效使用。若是只要使用索引就能得到最佳性能,那查询优化器的工做就简单了。但事实上,不正确的索引选择并不能得到最佳性能。所以,查询优化器的任务是只在索引或索引组合能提升性能时才选择它,而在索引检索有碍性能时则避免使用它。
建议的索引设计策略包括如下任务:
1. 了解数据库自己的特征。例如,它是频繁修改数据的联机事务处理 (OLTP) 数据库,仍是主要包含只读数据的决策支持系统 (DSS) 或数据仓库 (OLAP) 数据库?
2. 了解最经常使用的查询的特征。例如,了解到最经常使用的查询联接两个或多个表将有助于决定要使用的最佳索引类型。
3. 了解查询中使用的列的特征。例如,某个索引对于含有整数数据类型同时仍是惟一的或非空的列是理想索引。筛选索引适用于具备定义完善的数据子集的列。
4. 肯定哪些索引选项可在建立或维护索引时提升性能。例如,对现有某个大型表建立汇集索引将会受益于 ONLINE 索引选项。ONLINE 选项容许在建立索引或从新生成索引时继续对基础数据执行并发活动。
5. 肯定索引的最佳存储位置。非汇集索引能够与基础表存储在同一个文件组中,也能够存储在不一样的文件组中。索引的存储位置可经过提升磁盘 I/O 性能来提升查询性能。例如,将非汇集索引存储在表文件组所在磁盘之外的某个磁盘上的一个文件组中能够提升性能,由于能够同时读取多个磁盘。
或者,汇集索引和非汇集索引也可使用跨越多个文件组的分区方案。在维护整个集合的完整性时,使用分区能够快速而有效地访问或管理数据子集,从而使大型表或索引更易于管理。有关详细信息,请参阅已分区表和已分区索引。在考虑分区时,应肯定是否应对齐索引,即,是按实质上与表相同的方式进行分区,仍是单独分区。
# 设计索引。
索引设计是一项关键任务。索引设计包括肯定要使用的列,选择索引类型(例如汇集或非汇集),选择适当的索引选项,以及肯定文件组或分区方案布置。
# 肯定最佳的建立方法。按照如下方法建立索引:
* 使用 CREATE TABLE 或 ALTER TABLE 对列定义 PRIMARY KEY 或 UNIQUE 约束
SQL Server 数据库引擎自动建立惟一索引来强制 PRIMARY KEY 或 UNIQUE 约束的惟一性要求。默认状况下,建立的惟一汇集索引能够强制 PRIMARY KEY 约束,除非表中已存在汇集索引或指定了惟一的非汇集索引。默认状况下,建立的惟一非汇集索引能够强制 UNIQUE 约束,除非已明确指定惟一的汇集索引且表中不存在汇集索引。
还能够指定索引选项和索引位置、文件组或分区方案。
建立为 PRIMARY KEY 或 UNIQUE 约束的一部分的索引将自动给定与约束名称相同的名称。
* 使用 CREATE INDEX 语句或 SQL Server Management Studio 对象资源管理器中的“新建索引”对话框建立独立于约束的索引
必须指定索引的名称、表以及应用该索引的列。还能够指定索引选项和索引位置、文件组或分区方案。默认状况下,若是未指定汇集或惟一选项,将建立非汇集的非惟一索引。若要建立筛选索引,请使用可选的 WHERE 子句。
# 建立索引。
要考虑的一个重要因素是对空表仍是对包含数据的表建立索引。对空表建立索引在建立索引时不会对性能产生任何影响,而向表中添加数据时,会对性能产生影响。
对大型表建立索引时应仔细计划,这样才不会影响数据库性能。对大型表建立索引的首选方法是先建立汇集索引,而后建立任何非汇集索引。在对现有表建立索引时,请考虑将 ONLINE 选项设置为 ON。该选项设置为 ON 时,将不持有长期表锁以继续对基础表的查询或更新。
简单的建立索引,可采用以下语句:
CREATE INDEX IX_ProductVendor_VendorID
ON Purchasing.ProductVendor (VendorID, VendorName);
GOsql
索引用于快速找出在某个列中有一特定值的行。不使用索引,MySQL必须从第1条记录开始而后读完整个表直到找出相关的行。数据库
表越大,花费的时间越多。若是表中查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要看全部数据。架构
大多数MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)在B树中存储。只是空间列类型的索引使用R-树,而且MEMORY表还支持hash索引并发
大多数状况下索引能大幅度提升查询效率,但:数据库设计
尽可能减小like,但不是绝对不可用,”xxxx%” 是能够用到索引的,函数
想象一下,你在看一本成语词典,目录是按成语拼音顺序创建,查询需求是,你想找以 “一”字开头的成语(”一%“),和你想找包含一字的成语(“%一%”)工具
除了like,如下操做符也可用到索引:性能
<,<=,=,>,>=,BETWEEN,IN测试
<>,not in ,!=则不行优化
通常来讲,列的值惟一性过小(如性别,类型什么的),不适合建索引(怎样叫过小?一半说来,同值的数据超过表的百分之15,那就不必建索引了)
太长的列,能够选择只创建部分索引,(如:只取前十位作索引)
更新很是频繁的数据不适宜建索引(怎样叫很是?意会)
不能
一次查询只能用到一个索引,因此 首先枪毙 a,b各建索引方案
a仍是b? 谁的区分度更高(同值的最少),建谁!
固然,联合索引也是个不错的方案,ab,仍是ba,则同上,区分度高者,在前
where a = “xxx” 可使用 AB 联合索引
where b = “xxx” 则不可 (再想象一下,这是书的目录?)
因此,大多数状况下,有AB索引了,就能够不用在去建一个A索引了
like “%xxx”
not in , !=
对列进行函数运算的状况(如 where md5(password) = “xxxx”)
WHERE index=1 OR A=10
存了数值的字符串类型字段(如手机号),查询时记得不要丢掉值的引号,不然没法用到该字段相关索引,反之则不要紧
也即
select * from test where mobile = 13711112222;
但是没法用到mobile字段的索引的哦(若是mobile是char 或 varchar类型的话)
btw,千万不要尝试用int来存手机号(为何?本身想!要不本身试试)
索引包含了所需的所有值的话,就只select 他们,换言之,只select 须要用到的字段,如无必要,可尽可能避免select *
NULL会致使索引形同虚设,因此在设计表结构时应避免NULL 的存在(用其余方式表达你想表达的NULL,好比 -1?)
show index from tablename;
explain select ……;
在Sql Server2008中建立测试数据库Test,接着建立数据库表并插入数据,sql代码以下:
USE Test IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'emp_pay') DROP TABLE emp_pay GO USE Test IF EXISTS (SELECT name FROM sys.indexes WHERE name = 'employeeID_ind') DROP INDEX emp_pay.employeeID_ind GO USE Test GO CREATE TABLE emp_pay ( employeeID int NOT NULL, base_pay money NOT NULL, commission decimal(2, 2) NOT NULL ) INSERT emp_pay VALUES (1, 500, .10) INSERT emp_pay VALUES (2, 1000, .05) INSERT emp_pay VALUES (6, 800, .07) INSERT emp_pay VALUES (5, 1500, .03) INSERT emp_pay VALUES (9, 750, .06)
执行完上述sql代码之后咱们会发如今Test数据库中多出了一张emp_pay表,数据库表的内容以下图所示:
从上图咱们能够看出数据库中存储的数据排列顺序与咱们插入的前后顺序一致。接下来咱们查询employeeID=5的字段,执行以下sql代码:
USE Test SELECT * FROM emp_pay where employeeID=5
在SQL SERVER MANAGEMENT STUDIO中咱们点击“显示估计的查询计划”,会出现以下图所示的查询计划图:
其中表扫描的内容为:
接下来咱们为上述表添加汇集惟一索引,代码以下:
SET NOCOUNT OFF CREATE UNIQUE CLUSTERED INDEX employeeID_ind ON emp_pay (employeeID) GO
在执行完上述建立索引的代码之后,咱们再次查询emp_pay的数据内容,以下图所示:
从上图咱们能够发现数据内容已经按照employeeID进行了排序。
咱们继续执行前面关于employeeID=5的查询,点击“显示估计的执行计划”,出现以下图所示内容:
汇集索引查找的内容为:
当咱们为数据库表中的某一个字段建立索引,而且在查询语句中where子句中用到这样一个字段,那么查询效率会有所提升,咱们上述实验由于数据量的关系查询效率提升不明显。
咱们上面添加的索引是惟一汇集索引,所以当插入的数据在employeeID字段出现重复时会报错。假如咱们在建立索引以前数据字段出现重复,那么就不能建立惟一索引。
执行以下sql语句
update emp_pay set employeeID=7 where employeeID=1;
而后再次执行全表查询,咱们发现查询结果以下所示:
只要咱们更新了employeeID,那么最后的更新结果都会按照employeeID的值进行升序排序。这是由于咱们在employeeID上建立了索引的缘故。
咱们能够经过sql server management studio这个工具删除索引,也能够经过sql语句进行索引的删除,假设咱们要求删除在前面建立的索引employeeID_ind,那么sql语句以下代码所示:
DROP INDEX employeeID_ind ON emp_pay;