Select * 一定不走索引是否正确?

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
View Code

 

非聚集索引

 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
View Code

只有一列,肯定会走索引的


一张表有多列的情况

分三种情况:

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
View Code

小结:

只有聚集索引的表:如果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
View Code

 

小结:

只有非聚集索引的表:如果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
View Code

小结:

有聚集索引和非聚集索引的表:如果where后面包括创建聚集索引的时候的第一个字段,就会使用聚集索引查找

如果where后面包括创建非聚集索引的时候的第一个字段但不包括创建聚集索引的时候的第一个字段,就会使用索引查找

如果where后面不包括创建非聚集索引的时候的第一个字段和不包括创建聚集索引的时候的第一个字段,就会使用聚集索引扫描

1 SELECT * FROM [dbo].[Department] WHERE [GroupName]='销售组'


总结

其实走不走索引,关键取决于where后面包括还是不包括

创建聚集索引的时候的第一个字段

创建非聚集索引的时候的第一个字段

跟select *没有关系的,select * 最大的影响就是额外的IO开销

像“键查找” ,“RID查找”这些运算符就是额外的开销

键查找:到聚集索引里找其他字段的值

RID查找:到堆表里找其他字段的值

 

而在宋大侠的文章里:有关T-SQL的10个好习惯

他说到:

 造成额外的书签查找或是由查找变为扫描

由查找变为扫描,查找还是扫描决定于我刚才所说的话:

其实走不走索引,关键取决于where后面包括还是不包括

创建聚集索引的时候的第一个字段

创建非聚集索引的时候的第一个字段

如果大家不是很明白,可以看一下我所写的文章,我在文章里对聚集索引跟非聚集索引的研究还是比较透彻的

SQLSERVER聚集索引与非聚集索引的再次研究(上)

SQLSERVER聚集索引与非聚集索引的再次研究(下)

 

当然,您也不能把整个表的字段全部放到索引里,以消除额外IO开销,要针对实际情况,

该把要加入索引的字段就加入索引,不该把不用加入索引的字段不要加入索引

那么您刚才说:走索引不是where后面包括还是不包括创建索引的第一个字段吗???既然这样创建索引的时候只包括一个字段就好了

大家可以看一下SQLSERVER聚集索引与非聚集索引的再次研究(下),其实非聚集索引扫描也是很有用的

而聚集索引就只包括一个字段就行了,非聚集索引可以包括多个字段,详细还是看一下下面两篇文章吧o(∩_∩)o

SQLSERVER聚集索引与非聚集索引的再次研究(上)

SQLSERVER聚集索引与非聚集索引的再次研究(下)

 

 

不过大家还是不要用select * 比较好,老老实实写上字段名

有一些偷懒的人总是会有他的理由:

如果表结构改变我就不用修改代码 ,方便省事,一个select *搞定,项目这麽紧张还写上字段干嘛???

如果您是上面那种人,那好吧,当我没说过好了o(∩_∩)o

如有不对的地方,欢迎大家拍砖哦o(∩_∩)o

转载于:https://www.cnblogs.com/lyhabc/p/3290745.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当我们执行一条 SQL 查询语句使用 `SELECT *` 时,它会返回被查询表中所有的列。然而,如果在这个查询中索引失效了,意味着数据无法高效地被检索,可能会导致查询性能下降。 索引失效可能有多种原因。一种常见的原因是在查询中使用了不符合索引的操作符或函数。例如,使用`LIKE`操作符进行模糊匹配时,如果使用了通配符`%`在搜索模式的开始处,索引就会失效。此外,还有一些函数(如`LOWER()`或`UPPER()`)可以使索引失效。所以,在编写查询时要注意使用正确的操作符和函数,以确保索引生效。 另一个可能导致索引失效的原因是统计信息不准确。数据库通过统计信息来进行执行计划的优化和索引选择。如果统计信息过期或不准确,数据库可能会错误地选择不合适的索引,从而导致索引失效。为了解决这个问题,我们可以定期更新统计信息或手动收集统计信息,以确保索引使用正确。 此外,索引失效还可能是因为表中的数据分布不均匀。如果某个索引列上的数据分布不均匀,那么使用该列进行查询的时候,索引就可能失效。在这种情况下,我们可以考虑重新设计索引,或者使用其他的查询优化方法来改进性能。 总而言之,当 `SELECT *` 查询的索引失效时,我们需要检查查询中使用的操作符和函数是否符合索引,同时确保统计信息准确和数据分布均匀。通过这些方法,我们可以提高查询的性能并避免索引失效的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值