请问select count(*) from tablename where colname=value
这种查询是全表查询吗?请注意是加了where条件的。另外还有一个问题,sqlserver在进行查询的时候会加锁吗?为什么我在sqlserver2000客户端的锁里面看到很多select语句,不是只有dml语句才会对数据库加锁吗?
这种查询是全表查询吗?请注意是加了where条件的。另外还有一个问题,sqlserver在进行查询的时候会加锁吗?为什么我在sqlserver2000客户端的锁里面看到很多select语句,不是只有dml语句才会对数据库加锁吗?
select语句属于共享锁
http://blog.csdn.net/hdhai9451/article/details/9297763
比如我想查某个用户的信息个数,但是一COUNT就会全表查询,怎么避免这种情况呢?原来还有共享锁啊,学习了。。
select count(*) from tablename where colname=value
改为
select count(1) from tablename where colname=value
其中colname列加索引,速度会提高很多
count(1)不是第一个字段,而是常量去统计总记录。如果你要查询不重复username,你那样写是对的。select count(distinct username) from test
先查出所有满足条件的记录,再统计记录个数?和COUNT(主键id)相比哪个效率高?
1、如果有索引,不会存在表扫描,要么是索引扫描,要么是聚集索引扫描SET SHOWPLAN_ALL ON
go
select count(*)
from Person.Person where FirstName ='Kim'
GO
SET SHOWPLAN_ALL OFF
GO/*
StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- ------------------------------ ------------------------------ -------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------- ------------- ------------- ------------- ----------- ---------------- ----------- -------- ---------------------------------------------------------------- -------- ------------------
select count(*)
from Person.Person where FirstName ='Kim' 1 1 0 NULL NULL 1 NULL 1 NULL NULL NULL 0.1126245 NULL NULL SELECT 0 NULL
|--Compute Scalar(DEFINE:([Expr1002]=CONVERT_IMPLICIT(int,[Expr1006],0))) 1 2 1 Compute Scalar Compute Scalar DEFINE:([Expr1002]=CONVERT_IMPLICIT(int,[Expr1006],0)) [Expr1002]=CONVERT_IMPLICIT(int,[Expr1006],0) 1 0 8.962498E-06 11 0.1126245 [Expr1002] NULL PLAN_ROW 0 1
|--Stream Aggregate(DEFINE:([Expr1006]=Count(*))) 1 3 2 Stream Aggregate Aggregate NULL [Expr1006]=Count(*) 1 0 8.962498E-06 11 0.1126245 [Expr1006] NULL PLAN_ROW 0 1
|--Index Scan(OBJECT:([AdventureWorks2012].[Person].[Person].[IX_Person_LastName_FirstName_MiddleName]), WHERE:([AdventureWorks2012].[Person].[Person].[FirstName]=N'Kim')) 1 4 3 Index Scan Index Scan OBJECT:([AdventureWorks2012].[Person].[Person].[IX_Person_LastName_FirstName_MiddleName]), WHERE:([AdventureWorks2012].[Person].[Person].[FirstName]=N'Kim') NULL 14.10416 0.08090278 0.0221262 22 0.103029 NULL NULL PLAN_ROW 0 1*/2、如果换成查一个列名而不是count,还是扫描,可以证明扫描并不是count引起的,而是你的where条件。
SET SHOWPLAN_ALL ON
go
select FirstName--count(*)
from Person.Person where FirstName ='Kim'
GO
SET SHOWPLAN_ALL OFF
GO/*
StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- ------------------------------ ------------------------------ -------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------- ------------- ------------- ------------- ----------- ---------------- --------------------------------------------------- -------- ---------------------------------------------------------------- -------- ------------------
select FirstName--count(*)
from Person.Person where FirstName ='Kim' 1 1 0 NULL NULL 1 NULL 14.10416 NULL NULL NULL 0.103029 NULL NULL SELECT 0 NULL
|--Index Scan(OBJECT:([AdventureWorks2012].[Person].[Person].[IX_Person_LastName_FirstName_MiddleName]), WHERE:([AdventureWorks2012].[Person].[Person].[FirstName]=N'Kim')) 1 2 1 Index Scan Index Scan OBJECT:([AdventureWorks2012].[Person].[Person].[IX_Person_LastName_FirstName_MiddleName]), WHERE:([AdventureWorks2012].[Person].[Person].[FirstName]=N'Kim') [AdventureWorks2012].[Person].[Person].[FirstName] 14.10416 0.08090278 0.0221262 22 0.103029 [AdventureWorks2012].[Person].[Person].[FirstName] NULL PLAN_ROW 0 1
*/
SET SHOWPLAN_ALL ON
go
select count(*)
from Person.Person where BusinessEntityID =10798
GO
SET SHOWPLAN_ALL OFF
GO/*
StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- ------------------------------ ------------------------------ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------- ------------- ------------- ------------- ----------- ---------------- ----------- -------- ---------------------------------------------------------------- -------- ------------------
select count(*)
from Person.Person where BusinessEntityID =10798 1 1 0 NULL NULL 1 NULL 1 NULL NULL NULL 0.0032842 NULL NULL SELECT 0 NULL
|--Compute Scalar(DEFINE:([Expr1002]=CONVERT_IMPLICIT(int,[Expr1003],0))) 1 2 1 Compute Scalar Compute Scalar DEFINE:([Expr1002]=CONVERT_IMPLICIT(int,[Expr1003],0)) [Expr1002]=CONVERT_IMPLICIT(int,[Expr1003],0) 1 0 1.1E-06 11 0.0032842 [Expr1002] NULL PLAN_ROW 0 1
|--Stream Aggregate(DEFINE:([Expr1003]=Count(*))) 1 3 2 Stream Aggregate Aggregate NULL [Expr1003]=Count(*) 1 0 1.1E-06 11 0.0032842 [Expr1003] NULL PLAN_ROW 0 1
|--Clustered Index Seek(OBJECT:([AdventureWorks2012].[Person].[Person].[PK_Person_BusinessEntityID]), SEEK:([AdventureWorks2012].[Person].[Person].[BusinessEntityID]=CONVERT_IMPLICIT(int,[@1],0)) ORDERED FORWARD) 1 4 3 Clustered Index Seek Clustered Index Seek OBJECT:([AdventureWorks2012].[Person].[Person].[PK_Person_BusinessEntityID]), SEEK:([AdventureWorks2012].[Person].[Person].[BusinessEntityID]=CONVERT_IMPLICIT(int,[@1],0)) ORDERED FORWARD NULL 1 0.003125 0.0001581 9 0.0032831 NULL NULL PLAN_ROW 0 1
*/可以看到这次是seek而不是scan,再次证明扫描不是count引起的。4:sqlserver在进行查询的时候会加锁吗?为什么我在sqlserver2000客户端的锁里面看到很多select语句,不是只有dml语句才会对数据库加锁吗?
对于这个问题:2000只有悲观并发模式,也就是读会阻塞写(增删改),写会阻塞读。为了保证事务的ACID特性,默认隔离级别下的语句都加锁
5、count(1)在高版本的sqlserver中性能并不比*高,这个完全可以忽略。
最终的结论是
高版本中,COUNT(1)和COUNT(*)无区别。
count(*)的执行效率比count(col)高,因此可以用count(*)的时候就不要去用count(col)。
count(col)的执行效率比count(distinct col)高,不过这个结论的意义不大,这两种方法也是看需要去用。
如果是对特定的列做count的话建立这个列的非聚集索引能对count有很大的帮助。
如果经常count(*)的话则可以找一个最小的col建立非聚集索引以避免全表扫描而影响整体性能
为什么高版本中的count(*)是全表查询还能做到效率很高呢,如果是海量数据也没关系吗?
MSDN中明确载明:COUNT(*)不会使用任何特定列的信息
,COUNT(1)当然也不包含列至于扫描索引的问题,sql引擎会自行选择,只要确保表至少有个主键就可以了
如果你在列colname上建立索引了,那么就是索引查找,也就是index seek,速度会非常快。如果没建索引,那么一般就是全表扫描了。另外,select语句,在默认的read committed隔离级别下,不管是否在显式的事务begin tran ... commit tran/rollback tran中,都会对访问的资源申请共享锁,也就是S锁的,所以会阻塞其他的update语句或者delete语句的,因为这些语句会申请独占锁x锁,而x锁和s锁是不兼容的,所以这个时候update或delete就会等待,直到select语句释放S锁。
count(1)
count(列)如果求总数 都比*号很多
如果你在列colname上建立索引了,那么就是索引查找,也就是index seek,速度会非常快。如果没建索引,那么一般就是全表扫描了。另外,select语句,在默认的read committed隔离级别下,不管是否在显式的事务begin tran ... commit tran/rollback tran中,都会对访问的资源申请共享锁,也就是S锁的,所以会阻塞其他的update语句或者delete语句的,因为这些语句会申请独占锁x锁,而x锁和s锁是不兼容的,所以这个时候update或delete就会等待,直到select语句释放S锁。
count(*)不会是Index Seek吧
(
id int identity(1,1),
v varchar(30) default replicate('a',30)
)
insert into tab
values(default)
go 100
create index idx_tab_id on tab(id)--set statistics profile onselect COUNT(*)
from tab
如果你在列colname上建立索引了,那么就是索引查找,也就是index seek,速度会非常快。如果没建索引,那么一般就是全表扫描了。另外,select语句,在默认的read committed隔离级别下,不管是否在显式的事务begin tran ... commit tran/rollback tran中,都会对访问的资源申请共享锁,也就是S锁的,所以会阻塞其他的update语句或者delete语句的,因为这些语句会申请独占锁x锁,而x锁和s锁是不兼容的,所以这个时候update或delete就会等待,直到select语句释放S锁。
count(*)不会是Index Seek吧我试验了一下,用的是Index Scandrop table tabcreate table tab
(
id int identity(1,1),
v varchar(30) default replicate('a',30)
)
insert into tab
values(default)
go 100
create index idx_tab_id on tab(id)--set statistics profile onselect COUNT(*)
from tab