SQL性能低下
我有一个疑问如下SQL性能低下,sql,sql-server-2005,Sql,Sql Server 2005,我有一个疑问如下 SELECT COUNT(Id) FROM Table 该表包含3300万条记录—它在Id上包含一个主键,没有其他索引 查询需要30秒 实际执行计划显示它使用聚集索引扫描 我们分析了该表,发现它没有使用此链接中显示的第一个查询进行分段: 任何关于为什么这个查询如此缓慢以及如何修复它的想法 表定义: CREATE TABLE [dbo].[DbConversation]( [ConversationID] [int] IDENTITY(1,1) NOT NULL, [Con
SELECT COUNT(Id) FROM Table
该表包含3300万条记录—它在Id上包含一个主键,没有其他索引
查询需要30秒
实际执行计划显示它使用聚集索引扫描
我们分析了该表,发现它没有使用此链接中显示的第一个查询进行分段:
任何关于为什么这个查询如此缓慢以及如何修复它的想法
表定义:
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有关,而不是更大的数字,但令人惊讶的是,它有这种效果。磁盘上的MDF碎片是否可能是一个原因?这是一个经常读取/插入/更新的表吗?是否有与您的选择同步的更新/插入活动 我猜延迟是因为争论 我能够在我的dev服务器上在17秒内对189m行进行计数,但是没有任何其他东西能够命中该表 如果您不太担心争用或绝对准确性,您可以:
exec sp\u spaceused'MyTableName'
将根据元数据给出计数
如果您想要更精确的计数,但不一定关心它是否反映了并发的DELETE
或INSERT
活动,您可以使用NOLOCK
提示执行当前查询:
使用(NOLOCK)从MyTable中选择COUNT(id)
,它不会为您的查询获取行级锁,并且应该运行得更快。使用[DatabaseName]
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'
从sysindex dd中选择tbl.name、dd.rows
dd.id=tbl.id上的内部联接sysobjects tbl,其中dd.indid<2,tbl.xtype='U'
从sysindexes dd中选择sum(dd.rows)
dd.id=tbl.id上的内部联接sysobjects tbl,其中dd.indid<2,tbl.xtype='U'
通过使用这些查询,您可以在0-5秒内获取所有表的计数
根据您的要求使用where子句….想法:
- 使用
,这对于“多少行”(根据ANSI SQL)是正确的。即使ID是主键,因此不可为空,SQL Server也将统计ID,而不是行选择COUNT(*)
- 如果您可以接受近似计数,则使用sys.dm\u db\u partition\u stats。请看我的回答:
- 如果你能忍受脏读,请使用
和(NOLOCK)
计数来诊断性能缓慢并不是很有启发性。你能就实际问题和一些执行计划和/或IO统计数据提出一个新问题吗?@BonyT:正如@JNK建议的那样。发布一个新问题,包括实际的慢速查询、执行计划、表结构、索引等。参考站点是:仔细阅读帖子,他关心的不是select count(id)
而是查询的缓慢性能。这其实并不重要,因为无论你在括号内放什么,优化者都会有效地使用相同的计划。不过,有些人对使用“*”很挑剔。无论这与问题无关。@BonyT:如果你认为这是“挑剔的”,我建议你核实我是否知道,但count(col)可能不会给出与count(*)相同的计划。因此我的建议是的,我们确实是从*:)不-不是你挑剔-我之前有人建议我不要使用“*”-在某个地方有人开始了一个神话,认为使用*是不好的。我将我的问题调整为不使用*以避免该问题,因为它是主键-它不会为空!不是一个非常繁忙的数据库-争用不是问题(语句几乎总是需要完全相同的时间来响应30秒,使用NOLOCK提示也没什么区别。)@BonyT-那么您还有一些其他问题。这张桌子有多宽?这与计数没有直接关系,但它确实会影响SQL需要拉取多少页才能获得计数,这在较高的卷上可能很重要。您还有什么其他性能问题?接受,但可能永远不知道实际问题是什么,因为在其他人的地盘上,他们已经制定了解决方案,我理解。