Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL性能低下_Sql_Sql Server 2005 - Fatal编程技术网

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子句….

想法:

  • 使用
    选择COUNT(*)
    ,这对于“多少行”(根据ANSI SQL)是正确的。即使ID是主键,因此不可为空,SQL Server也将统计ID,而不是行

  • 如果您可以接受近似计数,则使用sys.dm\u db\u partition\u stats。请看我的回答:

  • 如果你能忍受脏读,请使用
    和(NOLOCK)


另一个想法是:当文件增加到1MB部分时,它可能会在文件系统中被分割。您无法通过SQL看到这一点,您可以通过磁盘碎片整理工具看到它。

问题1:您真的需要准确的计数吗?或者只是一个估计?两者都不是-这只是我们在观察到其他方面性能缓慢后运行的查询。我们很惊讶地发现它这么慢。我要尝试更新统计数据,但它们被设置为自动更新。你不能只使用一个常量吗?我的意思是,拥有3300万条记录与实际拥有33.212.293条记录之间的差异对您有何影响?@BonyT-使用
计数来诊断性能缓慢并不是很有启发性。你能就实际问题和一些执行计划和/或IO统计数据提出一个新问题吗?@BonyT:正如@JNK建议的那样。发布一个新问题,包括实际的慢速查询、执行计划、表结构、索引等。参考站点是:仔细阅读帖子,他关心的不是
select count(id)
而是查询的缓慢性能。这其实并不重要,因为无论你在括号内放什么,优化者都会有效地使用相同的计划。不过,有些人对使用“*”很挑剔。无论这与问题无关。@BonyT:如果你认为这是“挑剔的”,我建议你核实我是否知道,但count(col)可能不会给出与count(*)相同的计划。因此我的建议是的,我们确实是从*:)不-不是你挑剔-我之前有人建议我不要使用“*”-在某个地方有人开始了一个神话,认为使用*是不好的。我将我的问题调整为不使用*以避免该问题,因为它是主键-它不会为空!不是一个非常繁忙的数据库-争用不是问题(语句几乎总是需要完全相同的时间来响应30秒,使用NOLOCK提示也没什么区别。)@BonyT-那么您还有一些其他问题。这张桌子有多宽?这与
计数没有直接关系,但它确实会影响SQL需要拉取多少页才能获得计数,这在较高的卷上可能很重要。您还有什么其他性能问题?接受,但可能永远不知道实际问题是什么,因为在其他人的地盘上,他们已经制定了解决方案,我理解。