SQL Server 索引列的顺序——真的没关系吗
问题:
当设置表的索引时,在性能上有一个微妙的平衡:太多的索引将影响你的INSERT/UPDATE/DELETE操作。但是索引不足又将影响你的SELECT操作。本文将着眼于索引的列顺序和如何影响查询计划及性能。
解决方案:
示例SQLServer表和数据集:
-- Tablecreation logic
CREATE TABLE[dbo].[TABLE1]
([col1][int]
NOT NULL,[col2]
[int]NULL,[col3]
[int] NULL,[col4][varchar](50)NULL)
GO
CREATE TABLE[dbo].[TABLE2]
([col1][int]
NOT NULL,[col2]
[int]NULL,[col3]
[int] NULL,[col4][varchar](50)NULL)
GO
ALTER TABLEdbo.TABLE1ADD
CONSTRAINT PK_TABLE1
PRIMARY KEY
CLUSTERED (col1)
GO
ALTER TABLEdbo.TABLE2ADD
CONSTRAINT PK_TABLE2
PRIMARY KEY
CLUSTERED (col1)
GO
--Populate tables
DECLARE
@val INT
SELECT @val=1
WHILE @val< 1000
BEGIN
INSERT
INTO dbo.Table1(col1,col2,
col3,
col4)VALUES(@val,@val,@val,'TEST')
INSERT
INTO dbo.Table2(col1,col2,
col3,
col4)VALUES(@val,@val,@val,'TEST')
SELECT
@val=@val+1
END
GO
--Create multi-column index on table1
CREATE NONCLUSTEREDINDEX
IX_TABLE1_col2col3ONdbo.TABLE1(col2,col3)
WITH (STATISTICS_NORECOMPUTE=OFF,
IGNORE_DUP_KEY =
OFF,
ALLOW_ROW_LOCKS=ON,
ALLOW_PAGE_LOCKS =
ON)
ON [PRIMARY]
GO
在运行下面的代码前请先打开执行计划(Ctrl+M)和打开统计IO的语句:SET STATISTICS IO ON
单表查询例子:
在第一个例子里面,我们将使用在where子句中的一列来查询。第一个查询中where子句的索引使用第二列(col3),第二个查询使用第一列(col2)。注意这里使用了“DBCC DROPCLEANBUFFERS”,用于确保没有缓存带来的影响,代码如下:
DBCC DROPCLEANBUFFERS
GO
SELECT * FROM dbo.TABLE1 WHEREcol3=88
GO
DBCC DROPCLEANBUFFERS
GO
SELECT * FROM dbo.TABLE1 WHEREcol2=88
GO
执行后查看执行计划如下:


可以看到,第一个查询使用第二列(col3)的索引是在表上执行索引扫描,且没有用到刚才建立的索引。第二个查询使用了表查找,使得在表里只需要使用更少的资源。第一个查询读了6次,而第二个查询只读了4次。
执行查询后,你应该大概猜到,当表越来越大的时候,性能优势就显现出来了。
两表关联查询例子:
在下一个例子中,查询使用同样的where子句,但增加了一个inner join 关联另外一个表。第一个查询的where子句使用col3,并使用col2来关联表。
第二个查询的where子句使用col2,并使用col3来关联表。
同样,先执行DBCC DROPCLEANBUFFERS来确保缓存已经清空。代码如下:
DBCC DROPCLEANBUFFERS
GO
SELECT *
FROM dbo.TABLE1 INNER JOIN
dbo.TABLE2 ON dbo.TABLE1.col2 = dbo.TABLE2.col1
WHERE dbo.TABLE1.col3=255
GO
DBCC DROPCLEANBUFFERS
GO
SELECT *
FROM dbo.TABLE1 INNER JOIN
dbo.TABLE2 ON dbo.TABLE1.col3 = dbo.TABLE2.col1
WHERE dbo.TABLE1.col2=255
GO
执行计划如下:


从执行计划可以看到,当用于关联表的列也在索引中,但不是第一列时,会执行索引扫描。第二个查询中索引的第一列来关列,会使用索引查找。从IO来看,同样索引查找的读次数会更小。
总结:
从这些例子中,可以看到索引列的顺序对表的查询也有影响。当创建索引时,先确认你总是对尽可能小的集合进行操作,这意味着索引能从where子句中的列开始。另外,对order by子句中的列和SELECT中的列创建覆盖索引也有助于提高查询性能。这样可以不用在查询时执行书签查找。
在前面提到的,增加太多索引将引起insert/update/delete时对这些索引列的修改。所以,找到平衡点才是最重要的。
SQL Server 索引列的顺序——真的没关系吗的更多相关文章
- [转帖]SQL Server 索引中include的魅力(具有包含性列的索引)
SQL Server 索引中include的魅力(具有包含性列的索引) http://www.cnblogs.com/gaizai/archive/2010/01/11/1644358.html 上个 ...
- SQL Server索引进阶:第五级,包含列
原文地址: Stairway to SQL Server Indexes: Level 5, Included Columns 本文是SQL Server索引进阶系列(Stairway to SQL ...
- SQL Server索引设计 <第五篇>
SQL Server索引的设计主要考虑因素如下: 检查WHERE条件和连接条件列: 使用窄索引: 检查列的选择性: 检查列的数据类型: 考虑列顺序: 考虑索引类型(聚集索引OR非聚集索引): 一.检查 ...
- SQL Server索引总结二
从CREATE开始 通过显式的CREATE INDEX命令 在创建约束时作为隐含的对象 随约束创建的隐含索引 当向表中添加如下两种约束之一时,就会创建隐含索引. 主键约束(聚集索引) 唯一约束(唯一索 ...
- SQL Server索引 (原理、存储)聚集索引、非聚集索引、堆 <第一篇>
一.存储结构 在SQL Server中,有许多不同的可用排列规则选项. 二进制:按字符的数字表示形式排序(ASCII码中,用数字32表示空格,用68表示字母"D").因为所有内容都 ...
- SQL Server 索引结构及其使用(一)
转载:SQL Server 索引结构及其使用(一) 作者:freedk 一.深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录.微软的SQL SERVER提供了两种索引:聚集索引(clus ...
- SQL Server索引进阶:第十级,索引内部结构
原文地址: Stairway to SQL Server Indexes: Level 10,Index Internal Structure 本文是SQL Server索引进阶系列(Stairway ...
- SQL Server索引进阶:第九级,读懂执行计划
原文地址: Stairway to SQL Server Indexes: Level 9,Reading Query Plans 本文是SQL Server索引进阶系列(Stairway to SQ ...
- SQL Server索引进阶:第六级,标签
原文地址: Stairway to SQL Server Indexes: Level 6,Bookmarks 本文是SQL Server索引进阶系列(Stairway to SQL Server I ...
随机推荐
- HUNNU11354:Is the Name of This Problem
http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11354&courseid=0 Problem des ...
- android4.0 USB Camera示例(五个辅助)jpg压缩
前的最后一个 我们说,一个直接yuv变成jpg该功能 但是转换不成功 主要功能是yuv420转jpg的 根据研究发现 yuv420的序列是这种 YYYY YYYY UVUV 而yuv422的隔行扫描的 ...
- 树形dp专辑
hdu 2196 http://acm.hdu.edu.cn/showproblem.php?pid=2196 input 5//5个结点 1 1//表示结点2到结点1有一条权值为1的边 2 1//表 ...
- listary文件查找程序下载和使用
资源:PHP开发学习门户网站 地址:http://bbs.phpthinking.com/forum.php?mod=viewthread&tid=173 Listary 是一款有用的国产Wi ...
- android学习一些帖子
关于谷歌和苹果的帖子 http://news.eoe.cn/18576.html android无线调试的帖子: http://baoyz.com/android/2014/06/24/adb-wir ...
- Silverlight的Socket通信
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPwAAAGwCAIAAAACJJ+TAAAgAElEQVR4nO2deXgT5534Rdhskme7+9
- 使用cm-12.0源代码编译twrp
Select the newest branch available. This step is not necessary with Omni because Omni already includ ...
- rsync+inotify实现server实时备份
inotify实现对文件夹下文件进行监听的原理: inotify集成到内核中,通过内核提供的接口.使用inotify作为第三方的软件对文件夹变化进行监控. inotifywait命令能够对文件夹中的文 ...
- linux文件打开模式
文件打开 int open(const char *pathname, int flags, mode_t mode); 普通方式(Canonical mode) flags中没有设置O_SYN ...
- HTML5之Canvas影片广场
HTML5之Canvas影片广场 1.设计源代码 <!DOCTYPE html> <head> <meta charset="utf-8" /> ...