Select * 一定不走索引是否正確?
走索引指的是:SQL語句的執行計划用到了1、聚集索引查找 2、索引查找 ,並且查詢語句中需要有where子句
根據where子句的過濾條件,去聚集索引或非聚集索引那里查找記錄
一張表只有一列的情況:
聚集索引
1 USE [tempdb] 2 GO 3 CREATE TABLE t1 ( id INT ) 4 GO 5 CREATE CLUSTERED INDEX CIX_T1 ON [dbo].[t1](ID ASC) 6 GO 7 8 9 DECLARE @I INT 10 SET @I = 1 11 WHILE @I < 1000 12 BEGIN 13 INSERT INTO [dbo].[t1] ( [id] ) 14 SELECT @I 15 SET @I = @I + 1 16 END 17 18 SELECT * FROM [dbo].[t1] WHERE [id]=20

非聚集索引
1 USE [tempdb] 2 GO 3 4 CREATE TABLE t2 ( id INT ) 5 GO 6 CREATE NONCLUSTERED INDEX IX_T2 ON [dbo].[t2](ID ASC) 7 GO 8 9 10 DECLARE @I INT 11 SET @I = 1 12 WHILE @I < 1000 13 BEGIN 14 INSERT INTO [dbo].[t2] ( [id] ) 15 SELECT @I 16 SET @I = @I + 1 17 END 18 19 SELECT * FROM [dbo].[t2] WHERE [id]=20

只有一列,肯定會走索引的
一張表有多列的情況
分三種情況:
1、只有聚集索引
2、只有非聚集索引
3、有聚集索引和非聚集索引
只有聚集索引
1 --只有聚集索引 2 USE [tempdb] 3 GO 4 CREATE TABLE Department 5 ( 6 DepartmentID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, 7 Name NVARCHAR(200) NOT NULL , 8 GroupName NVARCHAR(200) NOT NULL , 9 Company NVARCHAR(300) , 10 ModifiedDate DATETIME NOT NULL DEFAULT ( GETDATE() ) 11 12 ) 13 14 15 DECLARE @i INT 16 SET @i=1 17 WHILE @i < 100000 18 BEGIN 19 INSERT INTO Department ( name, [Company], groupname ) 20 VALUES ( '銷售部'+CAST(@i AS VARCHAR(200)), '中國你好有限公司XX分公司', '銷售組' ) 21 SET @i = @i + 1 22 END 23 24 25 SELECT * FROM [dbo].[Department] WHERE [DepartmentID]=2


小結:
只有聚集索引的表:如果where后面不包括創建聚集索引的時候的第一個字段,就會使用聚集索引掃描
下面SQL語句會使用聚集索引查找,因為包括了創建聚集索引的時候的第一個字段
1 SELECT * FROM [dbo].[Department] WHERE [Company]='銷售部12' AND [DepartmentID]=12
只有非聚集索引
1 --只有非聚集索引 2 USE [tempdb] 3 GO 4 5 CREATE TABLE Department 6 ( 7 DepartmentID INT IDENTITY(1, 1) NOT NULL , 8 Name NVARCHAR(200) NOT NULL , 9 GroupName NVARCHAR(200) NOT NULL , 10 Company NVARCHAR(300) , 11 ModifiedDate DATETIME NOT NULL DEFAULT ( GETDATE() ) 12 13 ) 14 15 CREATE NONCLUSTERED INDEX IX_Department ON Department(DepartmentID ASC) 16 17 18 DECLARE @i INT 19 SET @i=1 20 WHILE @i < 100000 21 BEGIN 22 INSERT INTO Department ( name, [Company], groupname ) 23 VALUES ( '銷售部'+CAST(@i AS VARCHAR(200)), '中國你好有限公司XX分公司', '銷售組' ) 24 SET @i = @i + 1 25 END 26 27 28 SELECT * FROM [dbo].[Department] WHERE [Company]='銷售部12' AND [DepartmentID]=12


小結:
只有非聚集索引的表:如果where后面不包括創建非聚集索引的時候的第一個字段,就會使用表掃描或者索引掃描
下面SQL語句會使用非聚集索引查找,因為包括了創建非聚集索引的時候的第一個字段
1 SELECT * FROM [dbo].[Department] WHERE [Company]='銷售部12' AND [DepartmentID]=12
有聚集索引也有非聚集索引
1 --有聚集索引和非聚集索引 2 USE [tempdb] 3 GO 4 5 CREATE TABLE Department 6 ( 7 DepartmentID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, 8 Name NVARCHAR(200) NOT NULL , 9 GroupName NVARCHAR(200) NOT NULL , 10 Company NVARCHAR(300) , 11 ModifiedDate DATETIME NOT NULL DEFAULT ( GETDATE() ) 12 13 ) 14 15 CREATE NONCLUSTERED INDEX IX_Department ON Department(Company ASC) 16 17 18 DECLARE @i INT 19 SET @i=1 20 WHILE @i < 100000 21 BEGIN 22 INSERT INTO Department ( name, [Company], groupname ) 23 VALUES ( '銷售部'+CAST(@i AS VARCHAR(200)), '中國你好有限公司XX分公司', '銷售組' ) 24 SET @i = @i + 1 25 END



小結:
有聚集索引和非聚集索引的表:如果where后面包括創建聚集索引的時候的第一個字段,就會使用聚集索引查找
如果where后面包括創建非聚集索引的時候的第一個字段但不包括創建聚集索引的時候的第一個字段,就會使用索引查找
如果where后面不包括創建非聚集索引的時候的第一個字段和不包括創建聚集索引的時候的第一個字段,就會使用聚集索引掃描
1 SELECT * FROM [dbo].[Department] WHERE [GroupName]='銷售組'

總結
其實走不走索引,關鍵取決於where后面包括還是不包括
創建聚集索引的時候的第一個字段
創建非聚集索引的時候的第一個字段
跟select *沒有關系的,select * 最大的影響就是額外的IO開銷
像“鍵查找” ,“RID查找”這些運算符就是額外的開銷
鍵查找:到聚集索引里找其他字段的值
RID查找:到堆表里找其他字段的值
而在宋大俠的文章里:有關T-SQL的10個好習慣
他說到:
造成額外的書簽查找或是由查找變為掃描
由查找變為掃描,查找還是掃描決定於我剛才所說的話:
其實走不走索引,關鍵取決於where后面包括還是不包括
創建聚集索引的時候的第一個字段
創建非聚集索引的時候的第一個字段
如果大家不是很明白,可以看一下我所寫的文章,我在文章里對聚集索引跟非聚集索引的研究還是比較透徹的
當然,您也不能把整個表的字段全部放到索引里,以消除額外IO開銷,要針對實際情況,
該把要加入索引的字段就加入索引,不該把不用加入索引的字段不要加入索引
那么您剛才說:走索引不是where后面包括還是不包括創建索引的第一個字段嗎???既然這樣創建索引的時候只包括一個字段就好了
大家可以看一下SQLSERVER聚集索引與非聚集索引的再次研究(下),其實非聚集索引掃描也是很有用的
而聚集索引就只包括一個字段就行了,非聚集索引可以包括多個字段,詳細還是看一下下面兩篇文章吧o(∩_∩)o
不過大家還是不要用select * 比較好,老老實實寫上字段名
有一些偷懶的人總是會有他的理由:
如果表結構改變我就不用修改代碼 ,方便省事,一個select *搞定,項目這麽緊張還寫上字段干嘛???
如果您是上面那種人,那好吧,當我沒說過好了o(∩_∩)o
如有不對的地方,歡迎大家拍磚哦o(∩_∩)o
