我有一个查询如下;
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 提示 - 没有区别。我们都认为这与 Autogrowth 设置为 1Mb 而不是更大的数字有关,但很惊讶它有这种效果。磁盘上的 MDF 碎片可能是一个原因吗?
最佳答案
这是一个经常读取/插入/更新的表吗?是否有与您的选择同时进行的更新/插入事件?
我的猜测是延迟是由于争用。
我能够在我的开发服务器上在 17 秒内对 1.89 亿行进行计数,但是没有其他东西可以命中该表。
如果您不太担心争用或绝对准确性,您可以这样做:exec sp_spaceused 'MyTableName'
这将根据元数据给出一个计数。
如果您想要更精确的计数但不一定关心它是否反射(reflect)并发 DELETE
或 INSERT
您可以使用 NOLOCK
执行当前查询的事件暗示:SELECT COUNT(id) FROM MyTable WITH (NOLOCK)
这不会为您的查询获得行级锁,并且应该运行得更快。
关于sql - 缓慢的 SQL 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6426032/