sql 索引笔记
以下资料来自MSDN。
设计索引时,应考虑以下数据库准则:
- 一个表如果建有大量索引会影响 INSERT、UPDATE 和 DELETE 语句的性能,因为在表中的数据更改时,所有索引都须进行适当的调整。
- 避免对经常更新的表进行过多的索引,并且索引应保持较窄,就是说,列要尽可能少。
- 使用多个索引可以提高更新少而数据量大的查询的性能。大量索引可以提高不修改数据的查询(例如 SELECT 语句)的性能,因为查询优化器有更多的索引可供选择,从而可以确定最快的访问方法。
- 对小表进行索引可能不会产生优化效果,因为查询优化器在遍历用于搜索数据的索引时,花费的时间可能比执行简单的表扫描还长。因此,小表的索引可能从来不用,但仍必须在表中的数据更改时进行维护。
- 视图包含聚合、表联接或聚合和联接的组合时,视图的索引可以显著地提升性能。若要使查询优化器使用视图,并不一定非要在查询中显式引用该视图。有关详细信息,请参阅设计索引视图。
- 使用数据库引擎优化顾问来分析数据库并生成索引建议。有关详细信息,请参阅数据库引擎优化顾问概述。
设计索引时,应考虑以下查询准则:
- 为经常用于查询中的谓词和联接条件的所有列创建非聚集索引。
重要提示: 避免添加不必要的列。添加太多索引列可能对磁盘空间和索引维护性能产生负面影响。 - 涵盖索引可以提高查询性能,因为符合查询要求的全部数据都存在于索引本身中。也就是说,只需要索引页,而不需要表的数据页或聚集索引来检索所需数据,因此,减少了总体磁盘 I/O。例如,对某一表(其中对列 a、列 b 和列 c 创建了组合索引)的列 a 和列 b 的查询,仅仅从该索引本身就可以检索指定数据。
- 将插入或修改尽可能多的行的查询写入单个语句内,而不要使用多个查询更新相同的行。仅使用一个语句,就可以利用优化的索引维护。
- 评估查询类型以及如何在查询中使用列。例如,在完全匹配查询类型中使用的列就适合用于非聚集索引或聚集索引。有关详细信息,请参阅查询类型和索引。
设计索引时,应考虑以下列准则:
- 对于聚集索引,请保持较短的索引键长度。另外,对唯一列或非空列创建聚集索引可以使聚集索引获益。有关详细信息,请参阅聚集索引设计指南。
- 不能将 ntext、text、image、varchar(max)、nvarchar(max) 和 varbinary(max) 数据类型的列指定为索引键列。不过,varchar(max)、nvarchar(max)、varbinary(max) 和 xml 数据类型的列可以作为非键索引列参与非聚集索引。有关详细信息,请参阅具有包含性列的索引。
- xml 数据类型的列只能在 XML 索引中用作键列。有关详细信息,请参阅 xml 数据类型列的索引。
- 检查列的唯一性。在同一个列组合的唯一索引而不是非唯一索引提供了有关使索引更有用的查询优化器的附加信息。有关详细信息,请参阅唯一索引设计指南。
在列中检查数据分布。通常情况下,为包含很少唯一值的列创建索引或在这样的列上执行联接将导致长时间运行的查询。这是数据和查询的基本问题,通常不识别这
种情况就无法解决这类问题。例如,如果物理电话簿按姓的字母顺序排序,而城市里所有人的姓都是 Smith 或
Jones,则无法快速找到某个人。有关数据分布的详细信息,请参阅索引统计信息。
如果索引包含多个列,则应考虑列的顺序。用于等于 (=)、大于 (>)、小于 (<) 或 BETWEEN 搜索条件的 WHERE 子句或者参与联接的列应该放在最前面。其他列应该基于其非重复级别进行排序,就是说,从最不重复的列到最重复的列。
例如,如果将索引定义为LastName
、FirstName
,则该索引在搜索条件为WHERE LastName = 'Smith'
或WHERE LastName = Smith AND FirstName LIKE 'J%'
时将很有用。不过,查询优化器不会将此索引用于基于FirstName (WHERE FirstName = 'Jane')
而搜索的查询。- 考虑对计算列进行索引。有关详细信息,请参阅为计算列创建索引。
在确定某一索引适合某一查询之后,可以选择最适合具体情况的索引类型。索引包含以下特性:
- 聚集还是非聚集
- 唯一还是非唯一
- 单列还是多列
- 索引中的列是升序排序还是降序排序
您也可以通过设置选项(例如 FILLFACTOR)自定义索引的初始存储特征以优化其性能或维护。有关详细信息,请参阅设置索引选项。而且,通过使用文件组或分区方案可以确定索引存储位置来优化性能。有关详细信息,请参阅在文件组上放置索引。
在 SQL Server 2005 中,可以通过将非键列添加到非聚集索引的叶级别来扩展非聚集索引的功能。通过包含非键列,可以创建覆盖更多查询的非聚集索引。这是因为非键列具有下列优点:
- 它们可以是不允许作为索引键列的数据类型。
- 在计算索引键列数或索引键大小时,数据库引擎不考虑它们。
当查询中的所有列都作为键列或非键列包含在索引中时,带有包含性非键列的索引可以显著提高查询性能。这样可以实现性能提升,因为查询优化器可以在索引中找到所有列值;不访问表或聚集索引数据,从而减少磁盘 I/O 操作。
注意: |
---|
当索引包含查询引用的所有列时,它通常称为“覆盖查询”。 |
键列存储在索引的所有级别中,而非键列仅存储在叶级别中。有关索引级别的详细信息,请参阅表组织和索引组织。
可以将非键列包含在非聚集索引中,以避免超过当前索引大小的限制(最大键列数为 16,最大索引键大小为 900 字节)。数据库引擎计算索引键列数或索引键大小时,不考虑非键列。
例如,假设要为 AdventureWorks
示例数据库的 Document
表中的以下列建立索引:
Title nvarchar(50)
Revision nchar(5)
FileName nvarchar(400)
因为 nchar 和 nvarchar 数据类型的每个字符需要 2 个字节,所以包含这三列的索引将超出 900 字节的大小限制 10 个字节 (455 * 2)。使用 CREATE INDEX
语句的 INCLUDE
子句,可以将索引键定义为 (Title, Revision
),将 FileName
定义为非键列。这样,索引键大小将为 110 个字节 (55 * 2),并且索引仍将包含所需的所有列。下面的语句就创建了这样的索引。
USE AdventureWorks;
GO
CREATE INDEX IX_Document_Title
ON Production.Document (Title, Revision)
INCLUDE (FileName);
设计带有包含性列的非聚集索引时,请考虑下列准则:
- 在 CREATE INDEX 语句的 INCLUDE 子句中定义非键列。
- 只能对表或索引视图的非聚集索引定义非键列。
- 除 text、ntext 和 image 之外,允许所有数据类型。
- 精确或不精确的确定性计算列都可以是包含性列。有关详细信息,请参阅为计算列创建索引。
- 与键列一样,只要允许将计算列数据类型作为非键索引列,从 image、ntext 和 text 数据类型派生的计算列就可以作为非键(包含性)列。
- 不能同时在 INCLUDE 列表和键列列表中指定列名。
- INCLUDE 列表中的列名不能重复。
- 必须至少定义一个键列。最大非键列数为 1023 列。也就是最大的表列数减 1。
- 索引键列(不包括非键)必须遵守现有索引大小的限制(最大键列数为 16,总索引键大小为 900 字节)。
- 所有非键列的总大小只受 INCLUDE 子句中所指定列的大小限制;例如,varchar(max) 列限制为 2 GB。
修改已定义为包含性列的表列时,要受下列限制:
- 除非先删除索引,否则无法从表中删除非键列。
- 除进行下列更改外,不能对非键列进行其他更改:
- 将列的为空性从 NOT NULL 改为 NULL。
- 增加 varchar、nvarchar 或 varbinary 列的长度。
注意: 这些列修改限制也适用于索引键列。
重新设计索引键大小较大的非聚集索引,以便只有用于搜索和查找的列为键列。将覆盖查询的所有其他列设置为包含性非键列。这样,将具有覆盖查询所需的所有列,但索引键本身较小,而且效率高。
例如,假设要设计覆盖下列查询的索引。
USE AdventureWorks;
GO
SELECT AddressLine1, AddressLine2, City, StateProvinceID, PostalCode
FROM Person.Address
WHERE PostalCode BETWEEN N'98000' and N'99999';
若要覆盖查询,必须在索引中定义每列。尽管可以将所有列定义为键列,但键大小为 334 字节。因为实际上用作搜索条件的唯一列是 PostalCode
列(长度为 30 字节),所以更好的索引设计应该将 PostalCode
定义为键列并包含作为非键列的所有其他列。
下面的语句创建了一个覆盖查询的带有包含性列的索引。
USE AdventureWorks;
GO
CREATE INDEX IX_Address_PostalCode
ON Person.Address (PostalCode)
INCLUDE (AddressLine1, AddressLine2, City, StateProvinceID);
避免添加不必要的列。添加过多的索引列(键列或非键列)会对性能产生下列影响:
- 一页上能容纳的索引行将更少。这样会使 I/O 增加并降低缓存效率。
- 需要更多的磁盘空间来存储索引。特别是,将 varchar(max)、nvarchar(max)、varbinary(max) 或 xml 数据类型添加为非键索引列会显著增加磁盘空间要求。这是因为列值被复制到了索引叶级别。因此,它们既驻留在索引中,也驻留在基表中。
- 索引维护可能会增加对基础表或索引视图执行修改、插入、更新或删除操作所需的时间。
您应该确定修改数据时在查询性能上的提升是否超过了对性能的影响,以及是否需要额外的磁盘空间要求。有关评估查询性能的详细信息,请参阅查询优化。
当引用表的查询包含用以指定索引中键列的不同方向的 ORDER BY 子句时,指定键值存储在该索引中的顺序很有用。在这些情况下,索引就无需在查询计划中使用 SORT 运算符。因此,使得查询更有效。例如,Adventure Works Cycles 采购部门的买方不得不评估他们从供应商处购买的产品的质量。买方倾向于查验那些由具有高拒绝率的供应商发送的产品。检索数据以满足此条件需要将 Purchasing.PurchaseOrderDetail
表中的 RejectedQty
列按降序(由大到小)排序,并且将 ProductID
列按升序(由小到大)排序,如下列查询所示。
USE AdventureWorks;
GO
SELECT RejectedQty, ((RejectedQty/OrderQty)*100) AS RejectionRate,
ProductID, DueDate
FROM Purchasing.PurchaseOrderDetail
ORDER BY RejectedQty DESC, ProductID ASC;
此查询的下列执行计划显示了查询优化器使用 SORT 运算符按 ORDER BY 子句指定的顺序返回结果集。
如果使用与查询的 ORDER BY 子句中的键列匹配的键列创建索引,则无需在查询计划中使用 SORT 运算符,从而使查询计划更有效。
CREATE NONCLUSTERED INDEX IX_PurchaseOrderDetail_RejectedQty
ON Purchasing.PurchaseOrderDetail
(RejectedQty DESC, ProductID ASC, DueDate, OrderQty);
SQL Server 2005 数据库引擎 可以在两个方向上同样有效地移动。对于一个在 ORDER BY 子句中列的排序方向倒排的查询,
仍然可以使用定义为(RejectedQty DESC, ProductID ASC)
的索引。
例如,包含 ORDER BY 子句ORDER BY RejectedQty ASC, ProductID DESC
的查询可以使用该索引。
列谓词为下列之一的查询 | 查询说明和示例 | 考虑的索引 |
---|---|---|
与特定值完全匹配 |
搜索与特定值完全匹配的项,其中,查询使用 WHERE 子句指定列项。例如: SELECT EmployeeID, Title |
|
与 IN (x,y,z) 列表中的某个值完全匹配 |
搜索与指定值列表中的某个值完全匹配的项。例如: SELECT EmployeeID, Title |
|
值范围 |
搜索某个值范围,其中,查询指定的任何项的值在两个值之间。例如: SELECT ProductModelID, Name 或 WHERE ProductModelID >= 1 AND ProductModelID <= 5 |
|
表之间的联接 |
基于联接谓词,在一个表中搜索与另一个表中的某个行匹配的行。例如: SELECT a.ProductAssemblyID, b.Name, a.PerAssemblyQty |
|
LIKE 比较 |
搜索以特定字符串(如 abc%)开头的匹配行。例如: SELECT CountryRegionCode, Name |
|
排序或聚合 |
需要隐式或显式排序顺序或聚合 (GROUP BY)。例如: SELECT a.WorkOrderID, b.ProductID, a.OrderQty, a.DueDate |
排序列或聚合列的非聚集索引或聚集索引。 对于排序列,考虑为列指定 ASC 或 DESC 顺序。 |
PRIMARY KEY 或 UNIQUE 约束 |
搜索与插入和更新操作中的新索引键值重复的值,以强制 PRIMARY KEY 和 UNIQUE 约束。例如: INSERT INTO Production.UnitMeasure (UnitMeasureCode, Name, ModifiedDate) |
约束中定义的列的聚集索引或非聚集索引。 |
PRIMARY KEY/FOREIGN KEY 关系中的 UPDATE 或 DELETE 操作 |
在列参与 PRIMARY KEY/FOREIGN KEY 关系(无论带不带 CASCADE 选项)的更新或删除操作中搜索行。 |
外键列的非聚集索引或聚集索引。 |
列在选择列表中,但不在谓词中。 |
包含选择列表中未用于搜索和查找的一列或多列。例如: SELECT Title, Revision, FileName |
在 INCLUDE 子句中指定了 |
sql 索引笔记的更多相关文章
- sql 索引笔记--索引组织结构
非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点: 基础表的数据行不按非聚集键的顺序排序和存储. 非聚集索引的叶层是由索引页而不是由数据页组成. 既可以使用聚集索引来为表或视 ...
- sql 索引笔记2
以下资料都来于MSDN. 聚集索引指南: 一.此列和列值供内部使用,用户不能查看或访问. 查询注意事项 在创建聚集索引之前,应先了解数据是如何被访问的.考虑对具有以下特点的查询使用聚集索引: 使用运算 ...
- SQL索引学习-索引结构
前一阵无意中和同事讨论过一个SQL相关的题(通过一个小问题来学习SQL关联查询),很惭愧一个非常简单的问题由于种种原因居然没有回答正确,数据库知识方面我算不上技术好,谈起SQL知识的学习我得益于200 ...
- SQL学习笔记
SQL(Structured Query Language)学习笔记 [TOC] Terminal登录数据库 1.登录mysql -u root -p ; 2.显示所有数据库show database ...
- sql索引从入门到精通(十亿行数据测试报告)
原文:sql索引从入门到精通(十亿行数据测试报告) 导读部分 --------------------------------------------------------------------- ...
- SQL索引学习-聚集索引
这篇接着我们的索引学习系列,这次主要来分享一些有关聚集索引的问题.上一篇SQL索引学习-索引结构主要是从一些基础概念上给大家分享了我的理解,没有实例,有朋友就提到了聚集索引的问题,这里列出来一下: 其 ...
- 数据库性能优化:SQL索引
SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他的神秘面纱. 1.1 什么是索引? SQL索引有两种,聚集索引和非聚集索引 ...
- SQL索引一步到位
以下均非原创,仅供分享.学习!!! SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他的神秘面纱. 1.1 什么是索引? S ...
- {好文备份}SQL索引一步到位
SQL索引一步到位(此文章为"数据库性能优化二:数据库表优化"附属文章之一) SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百 ...
随机推荐
- [转] mongoose 之Shema
总 之见到我写点啥简直是奇迹,由于现在喜欢上玩转node.js +mongoose,个人爱好,靠近前端的又是英文文档,苦逼得很,悟出来一个写一个吧.之前喜欢误打误撞,网上搜索一点解决一下问题,后来实在 ...
- delphi TreeView 从数据库添加节点的四种方法
方法一:delphi中递归算法构建treeView 过程:通过读取数据库中table1的数据,来构建一颗树.table1有两个字段:ID,preID,即当前结点标志和父结点标志.所以整个树的表示为父母 ...
- 真的分治fft
以前学的分治fft f[i]=sigma(f[i-x]*g[x]),其中g[x]已知 那么我们可以用cdq分治来做(l,mid 对mid+1,t的影响) 而现在的$f[i]=sum(f(i-x)*f( ...
- 1.RN环境搭建,创建项目,使用夜神模拟调试
1.环境搭建(Yarn.React Native 的命令行工具(react-native-cli)) npm install -g yarn react-native-cli 具体参考 参见官方(中文 ...
- NSFileManager和NSFileHandler的作用, category的理解
NSFileManager类可以管理文件系统中的文件和目录,也可以定位.判断是否存在.创建.拷贝.删除文件和目录,还可以获得文件和目录的信息: 对于读写文件,NSFileManager只可以读写字符串 ...
- 利用vcard和qrcode.js生成二维码导入联系人
vCard是一种容许交换个人信息的数据规范,vCard数据格式的标识符是VCARD,vCard数据格式行是: 类型 [;参数]:值,具体的介绍百度都有,我们可以通过vcard来进行通讯录的保存,名片的 ...
- 2018牛客网暑假ACM多校训练赛(第四场)B Interval Revisited 动态规划
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round4-B.html 题目传送门 - https://www.no ...
- Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)
原文链接https://www.cnblogs.com/zhouzhendong/p/9256033.html 题目传送门 - CF873F 题意 给定长度为 $n$ 的字符串 $s$,以及给定这个字 ...
- BZOJ3862 Little Devil I 树链剖分
原文链接http://www.cnblogs.com/zhouzhendong/p/8081514.html 题目传送门 - BZOJ3862 题意概括 一棵树,n个点,边权为黑或者白,支持3重操作: ...
- HDU2586How far away? LCA
去博客园看该题解 题意 给出一棵树,以及每条边的权值,给出一些询问,每个询问是2个节点,求每个询问对应的2个节点的距离. 算法 LCA_Tarjan 代码 #include <cstring&g ...