C# 查询较新记录时使用存储过程进行缓慢查询

C# 查询较新记录时使用存储过程进行缓慢查询,c#,asp.net,sql,sql-server,sql-server-2008,C#,Asp.net,Sql,Sql Server,Sql Server 2008,对不起,下面的文字墙 我这里有点奇怪的问题。我有一个很大的表,用于存储过去几天来自Exchange2007的邮件跟踪日志信息。记录数以百万计(约1000-1200万),每30分钟我会通过PowerShell计划任务从所有传输服务器批量插入任何新日志 每天晚上我都会执行一次维护任务,清理所有超过一天的日志,这样桌子就不会变得太大,不过如果可以的话,我想把日志保留更长时间 该表称为MessageTracking,它有一个主键,它是一个IDENTITY int列,[MessagelogID],每个记录

对不起,下面的文字墙

我这里有点奇怪的问题。我有一个很大的表,用于存储过去几天来自Exchange2007的邮件跟踪日志信息。记录数以百万计(约1000-1200万),每30分钟我会通过PowerShell计划任务从所有传输服务器批量插入任何新日志

每天晚上我都会执行一次维护任务,清理所有超过一天的日志,这样桌子就不会变得太大,不过如果可以的话,我想把日志保留更长时间

该表称为MessageTracking,它有一个主键,它是一个IDENTITY int列,[MessagelogID],每个记录递增1

[date-time]列上有一个非聚集索引,用于[date-time]asc

发件人和收件人字段上有全文索引

用户可以通过我在C#Asp.net中编写的前端网页来搜索该表。该页面允许使用4个搜索字段进行非常基本的搜索:

  • 开始日期时间
  • 结束日期时间
  • 寄件人
  • 接受者
这会将查询传递到一个存储过程,该存储过程实际上会将记录拉回来。存储过程称为GetMessageTracking

现在谈谈我的奇怪问题。此查询在0秒内返回结果,速度非常快:

USE [DATABASENAME]
GO

DECLARE @return_value int

EXEC    @return_value = [dbo].[GetMessageTracking]
        @maximumRows = 20,
        @startRowIndex = 0,
        @sortExpression = N'[date-time]',
        @SearchStartDate = N'2012-03-27 13:51',
        @SearchEndDate = N'2012-03-27 20:09',
        @SearchSender = N'user@domain.com',
        @SearchRecipient = N'Default'

SELECT  'Return Value' = @return_value

GO
如果我将@SearchStartDate参数更改为再向前一小时,即N'2012-03-27 14:51',那么它在很长一段时间内不会完成

我只能假设我的datetime索引存在重大问题,因为全文目录通常是空闲的。我面临的挑战之一是,我几乎每小时插入数千条记录,索引(IX_DateTime)很快变得支离破碎,但我想不出一个好办法来阻止这种情况的发生

所以我的问题有两个:

1) 在搜索较新的记录时,查询需要一段时间,我如何才能看到导致此问题的原因

2) 当有大量插入时,有什么索引技巧吗

我想可能是执行计划导致了这种奇怪的行为,但不,这似乎没问题。我尝试将WITH RECOMPILE选项添加到查询中,但没有任何区别。我也清除了执行计划缓存,但没有任何效果

我很确定我的问题完全在于我的索引


谢谢

使用重新编译是很好的第一步。因此,我们可以排除参数嗅探在问题出现时的可能性

请发布执行计划的截图。我想这样问题就会清楚了。我猜这是一个统计问题。查询优化器认为没有日期时间>=N'2012-03-27 14:51'的行,因此选择了错误的计划。尝试运行sp_updatestats


至于你的问题#2:将索引填充设置为50-80范围内的某个值。

由于插入和删除的数量很大,表上可能有分段索引。以下脚本(取自)将为您提供有关碎片的信息

select object_name(i.object_id) as table_name,
       indexstats.avg_fragmentation_in_percent
from sys.dm_db_index_physical_stats(db_id(), null, null, null, 'detailed') indexstats
inner join sys.indexes i 
   on i.object_id = indexstats.object_id and i.index_id = indexstats.index_id
where indexstats.avg_fragmentation_in_percent > 20
如果发现大量碎片,可以重建或重新组织索引。SQL授权机构有另一个提供以下信息的授权机构

索引重建:此过程删除现有索引并重新创建索引

alter index all on schema.table_name rebuild
alter index all on schema.table_name reorganize
索引重组:此过程物理重组索引的叶节点

alter index all on schema.table_name rebuild
alter index all on schema.table_name reorganize

我想你已经发现了你自己的问题——大量写作导致的索引碎片化


您可以通过调整表格和索引增长所需的填充(磁盘空间)来帮助缓解此问题。

谢谢您和您下面的人提出的好建议,我会在有时间的时候查看它们,可能是明天或今晚晚些时候,等待其他内容!嗨,我正在SQL作业中运行这个大的旧脚本,每天晚上02:00-。现在运行它会显示以下内容:[dbo].[MessageTracking].[IX_DateTime]:碎片:57.3457%页面计数:40418操作:在[dbo].[MessageTracking]上重建ALTER INDEX[IX_DateTime]。[MessageTracking]重建在这里看不到上传图像的简单方法,因此我已将其上传到imgur。今晚无法复制一个和昨天一样长的查询,但我做了一个需要26秒才能运行的查询,我记录了使用的执行计划。-这看起来怎么样?DateTime索引返回了多少行,表中有多少行?我认为问题在于,对于某些数据,全文匹配函数会对几乎所有的行进行排序。这就需要从查询的右侧返回许多行,以填充您请求的页面大小。您可以通过从查询中删除全文过滤器来检查这一点。现在应该非常快了。关于第2点,我已经为测试将索引设置为70%的填充因子,但是我在前面读过一件事:当数据总是添加到表的末尾时,填充因子小于100(或0)实际上会降低性能。由于我总是使用标识列进行插入,我假设这适用于我?这通常是正确的,但索引中的数据不会按主键顺序插入。它按索引顺序插入,这可能会有所不同。我不知道情况是否如此,所以我建议你试试。如果对您没有任何帮助,您应该恢复更改。查询实际上返回了0个结果,因为发送的查询没有匹配项,但在IX_DateTime的执行计划中,它表示实际行数为327392。您是否建议我只在开始日期和结束日期之间搜索,并查看性能,而将发件人和收件人字段保留在t之外