执行极慢的 SELECT
Posted
技术标签:
【中文标题】执行极慢的 SELECT【英文标题】:Extremely Slow Performing SELECT 【发布时间】:2009-12-07 14:32:55 【问题描述】:我有一个包含 7,526,511 条记录的表,其定义如下:
/****** Object: Table [dbo].[LogSearches] Script Date: 12/07/2009 09:23:14 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[LogSearches](
[ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
[Acct_ID] [int] NULL,
[RecordCount] [int] NOT NULL,
[PageNumber] [int] NOT NULL,
[Site_ID] [int] NOT NULL,
[SearchAPI] [bit] NOT NULL,
[FormSearch] [bit] NOT NULL,
[IPAddress] [varchar](15) NOT NULL,
[Domain] [nvarchar](150) NOT NULL,
[ScriptName] [nvarchar](500) NOT NULL,
[QueryString] [varchar](max) NULL,
[Referer] [nvarchar](1024) NOT NULL,
[SearchString] [nvarchar](max) NOT NULL,
[UserAgent] [nvarchar](2048) NULL,
[Processed] [datetime] NOT NULL,
[Created] [datetime] NOT NULL,
[IntegerIP] [int] NULL,
CONSTRAINT [PK_LogSearches] PRIMARY KEY CLUSTERED
(
[ID] 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
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[LogSearches] ADD CONSTRAINT [DF_LogSearches_Processed] DEFAULT (getdate()) FOR [Processed]
GO
ALTER TABLE [dbo].[LogSearches] ADD CONSTRAINT [DF_LogSearches_Created] DEFAULT (getdate()) FOR [Created]
GO
执行计划如下所示:
StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
---------------------------------------------------------------------------------------- ----------- ----------- ----------- ------------------------------ ------------------------------ -------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------- ------------- ------------- ----------- ---------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------- ---------------------------------------------------------------- -------- ------------------
SELECT TOP 1 * FROM LogSearches 1 1 0 NULL NULL 1 NULL 1 NULL NULL NULL 0.0032832 NULL NULL SELECT 0 NULL
|--Top(TOP EXPRESSION:((1))) 1 2 1 Top Top TOP EXPRESSION:((1)) NULL 1 0 1E-07 11848 0.0032832 [LOALogs].[dbo].[LogSearches].[ID], [LOALogs].[dbo].[LogSearches].[Acct_ID], [LOALogs].[dbo].[LogSearches].[RecordCount], [LOALogs].[dbo].[LogSearches].[PageNumber], [LOALogs].[dbo].[LogSearches].[Site_ID], [LOALogs].[dbo].[LogSearches].[SearchAPI], [LOALo NULL PLAN_ROW 0 1
|--Clustered Index Scan(OBJECT:([LOALogs].[dbo].[LogSearches].[PK_LogSearches])) 1 3 2 Clustered Index Scan Clustered Index Scan OBJECT:([LOALogs].[dbo].[LogSearches].[PK_LogSearches]) [LOALogs].[dbo].[LogSearches].[ID], [LOALogs].[dbo].[LogSearches].[Acct_ID], [LOALogs].[dbo].[LogSearches].[RecordCount], [LOALogs].[dbo].[LogSearches].[PageNumber], [LOALogs].[dbo].[LogSearches].[Site_ID], [LOALogs].[dbo].[LogSearches].[SearchAPI], [LOALo 1 2956.71 8.279319 11848 0.0032831 [LOALogs].[dbo].[LogSearches].[ID], [LOALogs].[dbo].[LogSearches].[Acct_ID], [LOALogs].[dbo].[LogSearches].[RecordCount], [LOALogs].[dbo].[LogSearches].[PageNumber], [LOALogs].[dbo].[LogSearches].[Site_ID], [LOALogs].[dbo].[LogSearches].[SearchAPI], [LOALo NULL PLAN_ROW 0 1
(3 row(s) affected)
当我运行查询时,它不会在任何合理的时间范围内完成。我已经让查询运行了 5 分钟以上,但它仍然没有返回我要求的单行。这种缓慢的 SELECT 性能会对数据库产生其他影响,例如难以删除我们不再需要的行。
你知道我的瓶颈可能在哪里吗? 98 gig 数据库及其日志在 SQL Server 2008 上运行在 4 磁盘 RAID 10 上,驱动器上有超过 100 gig 的可用空间。
【问题讨论】:
您确定您选择的行没有被另一个进程锁定的行/页面/数据库阻塞吗?尝试在查询末尾添加 (NoLock) 看看是否有帮助 使用(NOLOCK)时是否返回 它确实返回了 NOLOCK。看起来我犯了一个菜鸟错误,因为我一直在处理这张桌子。该死的。长。我要花很长时间才能清除我们不再需要的行。 如果您使用的是 SQL 2005 /8,那么当您的危机结束时,您可能希望查看日志文件的分区表;您可以对数据进行分区,以便通过少量维护将当前月份的日志数据放入一个表中,而其余的则在另一个表中。可以是一个非常有用的工具;如果您在企业中,您可以将内容设置为离线或只读,这样会更好。 是的,我绝对有兴趣按日期对表格进行分区,我只需要弄清楚如何使用它。那里的文档似乎过于技术性,因为设置起来应该相当简单。 【参考方案1】:您是否检查过您是否遇到了阻塞问题?
【讨论】:
最近几天我一直在和这张桌子打架,但这次没有。看来这毕竟可能是问题所在。我在尝试从该表中删除记录时遇到了连续问题,并错误地假设它是相同的旧东西。【参考方案2】:创建另一个具有所需结构的表并在那里复制/“泵送”数据,然后删除旧表并重命名新表是否有用?您可能需要针对特定 id 范围“批量”执行此操作:
INSERT INTO LogSearches_new ... SELECT * FROM LogSearches WHERE ID BETWEEN 1 AND 999999
【讨论】:
不幸的是,当我尝试它时,该解决方案引起的问题与原始删除一样多:-(。我认为我需要解决磁盘 I/O 问题以加快速度。一直运行 PerfMon 24 小时,让我们看看它要说什么。以上是关于执行极慢的 SELECT的主要内容,如果未能解决你的问题,请参考以下文章
极慢的 Wordpress WooCommerce 网站(在管理面板和最终用户中)