博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL Server 索引列的顺序——真的没关系吗
阅读量:6638 次
发布时间:2019-06-25

本文共 2249 字,大约阅读时间需要 7 分钟。

原文:

翻译自:

问题:

当设置表的索引时,在性能上有一个微妙的平衡:太多的索引将影响你的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时对这些索引列的修改。所以,找到平衡点才是最重要的。

转载地址:http://yqivo.baihongyu.com/

你可能感兴趣的文章
Cool tool: Linux字符画figlet
查看>>
[转]windows下安装python MySQLdb及问题解决
查看>>
关于浏览器兼容问题:获取div的值
查看>>
2019-4-22 linux学习
查看>>
PKUWC2019游记
查看>>
控制转移指令分类与机器码
查看>>
BZOJ5279: [Usaco2018 Open]Disruption
查看>>
HDU 1312 Red and Black
查看>>
HDU 2871 Memory Control
查看>>
poj 1811 Prime Test
查看>>
ios 续费 问题 冰山一角
查看>>
一些奇怪的坑+好东西
查看>>
【Dairy】2016.10.24 - made 嘲讽垃圾
查看>>
查找表包含的页和页所在的表
查看>>
快速高效实现微信小程序图片上传与腾讯免费5G存储空间的使用
查看>>
vue实现PC端调用摄像头拍照人脸录入、移动端调用手机前置摄像头人脸录入、及图片旋转矫正、压缩上传base64格式/文件格式...
查看>>
mvc笔记(2012-11-02)
查看>>
求二叉排序树的镜像
查看>>
在StoryBoard对UICollectionViewCell 进行Autolayout是遇到的Xcode6.01的BUG
查看>>
后缀自动机板子和一些用法
查看>>