【IT168 专稿】当我们希望获得一个表中符合条件的记录的行数时,一般借助于T-SQL函数count(*)来实现。不过,如果你的表中包含了数百万条记录,返回整个表的记录数可能需要花费较长时间,会导致查询性能非常低。
1.Count()函数
DBA们都知道如何使用count(*)函数,也知道它对性能的影响。SQL Server需要进行一次完整的索引/表扫描,才能返回表的记录总数。建议DBA不要针对这个表使用聚合函数count(),因为它会影响数据库的性能。接下来我们在示例数据库AdventureWorkstation的查询分析器中执行以下查询语句:
use AdventureWorks
go
select count (*) from Sales.SalesOrderDetail
go
select count (*) from Sales.SalesOrderDetail
查询分析器返回的结果为121317行。
当我们点击SQL Server 2005 Management Studio工具栏中的“显示预计的执行计划”图标时,我们可以看到如下图示:

图1 查看count(*)执行计划
如上图所示,该函数执行过程中将从右至左执行如下操作:
•对整个表进行索引扫描,这是一个相当耗时的过程。
•接下来执行流聚合。
2.新方法row_count()
在SQL Server 2005的对象目录视图(Object Catalog Views)包含如下信息:sys.partitions和sys.allocation_units被用来获得整个表的记录总数。这个函数可以在SQL Server 2005中使用。
sys.partitions视图
sys.partitions视图包含了数据库中所有表和索引的每个分区在表中对应的每一行。即使SQL Server 2005中的所有表和索引并未显式分区,也至少在这个视图中包含一个分区。
该视图包含如下字段,它们将被用于这个新方法:
字段名称 | 数据类型 | 描述 |
partition_id | bigint | 分区的ID,它在一个数据库中是唯一的。 |
object_id | int | 分区所属表的ID。每个表至少包含一个分区。 |
index_id | int | 分区所属对象内索引的ID。 0:heap表 1:具有集群索引 |
rows | bigint | 分区中表的行数。 |
sys.allocation_units视图
sys.allocation_units视图包含了数据库中的每个分配单元在表中的每一行。
该视图中可以被新方法使用的字段如下:
字段名称 | 数据类型 | 描述 |
container_id | bigint | container_id=sys.partitions.partition_id |
Type | tinyint | 0 = 已删除 1 = 行内数据(除LOB之外的所有数据类型) 2 = 大型对象(LOB)数据(text、ntext、 image、xml) 3 = 行溢出数据 |
在这个新用户自定义函数row_count中,[sys.partitions]视图与[sys.allocation_units]视图是相关联的。过滤器的选择基于如下标准:
·[sys.allocation_units].type=1,只获得行数据,不包含诸如text、ntext、image等类型的大型对象。
·[sys.partitions].index_id为0表示是heap表,为1表示是集群表。
·[sys.partitions].rows不为空。
用户自定义函数row_count在每一个数据库中被执行,因此其权限为public。