我的查询如下;
SELECT COUNT(Id) FROM Table
该表包含3300万条记录 - 它包含Id上的主键,没有其他索引。
查询需要30秒。
实际执行计划显示它使用聚簇索引扫描。
我们已对该表进行了分析,发现该表未使用此链接中显示的第一个查询进行分段:http://sqlserverpedia.com/wiki/Index_Maintenance。
关于为什么这个查询如此缓慢以及如何解决它的任何想法。
表定义:
CREATE TABLE [dbo].[DbConversation](
[ConversationID] [int] IDENTITY(1,1) NOT NULL,
[ConversationGroupID] [int] NOT NULL,
[InsideIP] [uniqueidentifier] NOT NULL,
[OutsideIP] [uniqueidentifier] NOT NULL,
[ServerPort] [int] NOT NULL,
[BytesOutbound] [bigint] NOT NULL,
[BytesInbound] [bigint] NOT NULL,
[ServerOutside] [bit] NOT NULL,
[LastFlowTime] [datetime] NOT NULL,
[LastClientPort] [int] NOT NULL,
[Protocol] [tinyint] NOT NULL,
[TypeOfService] [tinyint] NOT NULL,
CONSTRAINT [PK_Conversation_1] PRIMARY KEY CLUSTERED
(
[ConversationID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
我注意到的一件事是数据库设置为以1Mb块增长。
这是一个实时系统,所以我们限制了我们可以玩什么 - 任何想法?
更新:
好的 - 我们通过在适当的列上添加新的非聚集索引来提高实际感兴趣的查询的性能,因此它不再是一个关键问题。
SELECT COUNT
仍然很慢 - 尝试使用NOLOCK提示 - 没有区别。
我们都认为这与设置为1Mb的Autogrowth有关,而不是更大的数字,但令人惊讶的是它有这种效果。磁盘上的MDF碎片可能是可能的原因吗?
答案 0 :(得分:5)
这是经常阅读/插入/更新的表吗?是否有与您的选择同步的更新/插入活动?
我的猜测是延迟是由于争用。
我可以在我的开发服务器上在17秒内对189m行进行计数,但没有其他任何内容可以访问该表。
如果您不太担心争用或绝对准确性,您可以这样做:
exec sp_spaceused 'MyTableName'
将根据元数据进行计数。
如果您想要更精确的计数但不一定关心它是否反映了并发DELETE
或INSERT
活动,您可以使用NOLOCK
提示执行当前查询:
SELECT COUNT(id) FROM MyTable WITH (NOLOCK)
,它不会为您的查询获取行级锁定,并且应该运行得更快。
答案 1 :(得分:2)
思考:
使用SELECT COUNT(*)
对“行数”是正确的(根据ANSI SQL)。即使ID是PK而且因此不可为空,SQL Server也会计算ID。不是行。
如果您可以使用近似计数,则使用sys.dm_db_partition_stats。请在此处查看我的回答:Fastest way to count exact number of rows in a very large table?
如果您可以使用脏读,请使用WITH (NOLOCK)
答案 2 :(得分:1)
use [DatabaseName]
select tbl.name, dd.rows from sysindexes dd
inner join sysobjects tbl on dd.id = tbl.id where dd.indid < 2 and tbl.xtype = 'U'
select sum(dd.rows)from sysindexes dd
inner join sysobjects tbl on dd.id = tbl.id where dd.indid < 2 and tbl.xtype = 'U'
通过使用这些查询,您可以在0-5秒内获取所有表的计数
根据您的要求使用where子句.....
答案 3 :(得分:0)
另一个想法:当文件以1MB部分增长时,它可能在文件系统上碎片化。你无法通过SQL看到它,你可以使用磁盘碎片整理工具看到它。