我有这个评论表(超过1百万行),每天大约有10,000个插入和大约100,000次查询,以及轻微的删除和更新.获取注释的查询会导致性能问题,有时它会锁定整个数据库,并且我会收到很多超时.请帮我调整我的索引和其他任何东西,以便它表现更好.下面我包含了有关它的信息,如果你需要更多,请询问.我每天重建所有索引并在2008服务器上运行sql server 2008网络版.
谢谢 :)
结构体:
id (int, identity)
profile_id (int)
owner_id (int)
added_date (datetime)
comments varchar(4000)
logical_delete (datetime)
指标:
id (PK, clustered)
profile_id (70% fill)
owner_id (70% fill)
added_date (70% fill)
profile_id + logical_delete (70%)
查询:
select
c.id, c.owner_id, c.comments, c.is_public, c.added_date,
u.first_name, u.last_name, c.profile_id
from [profile_comment] c with(nolock)
inner join [user] u with(nolock) on u.id = c.owner_id
where c.profile_id = @profile_id and c.logical_delete is null
order by c.added_date desc
执行计划:
|--Nested Loops(Inner Join, OUTER REFERENCES:([c].[owner_id], [Expr1005]) WITH ORDERED PREFETCH)
|--Sort(ORDER BY:([c].[added_date] DESC)) **[5%]**
| |--Nested Loops(Inner Join, OUTER REFERENCES:([c].[id], [Expr1004]) WITH UNORDERED PREFETCH) **[0%]**
| |--Index Seek(OBJECT:([DB].[dbo].[profile_comment].[IX_profile_comment_combined1] AS [c]), SEEK:([c].[profile_id]=(1) AND [c].[logical_delete]=NULL) ORDERED FORWARD) **[1%]**
| |--Clustered Index Seek(OBJECT:([JakLeci].[dbo].[profile_comment].[PK__profile_comment__primary] AS [c]), SEEK:([c].[id]=[JakLeci].[dbo].[profile_comment].[id] as [c].[id]) LOOKUP ORDERED FORWARD) **[47%]**
|--Clustered Index Seek(OBJECT:([DB].[dbo].[user].[PK__user__id] AS [u]), SEEK:([u].[id]=[DB].[dbo].[profile_comment].[owner_id] as [c].[owner_id]) ORDERED FORWARD) **[47%]**
最佳答案 (profile_id,added_date DESC)上的聚簇索引应该可以解决问题.这将通过profile_id快速查找,已经按added_date排序.剩下的唯一操作是对logical_delete进行过滤,对用户进行循环连接(应该在user_id上进行集群).
根据返回的行数,您仍然可以读取相当多的磁盘.您的评论专栏非常广泛.您可能需要考虑限制added_date(或TOP)返回的行数,或缓存结果.
我无法想象这会导致高CPU使用率,并且您正在使用NOLOCK,因此您不应该阻止其他查询.如果这确实是导致超时的原因,那么它必须是I / O.您可能想要检查内存使用情况和磁盘子系统,以确保您获得了不错的性能.检查前后的逻辑读取和CPU时间,以确定您是否正在帮助.
您也可以删除一些索引来加速插入.除了浪费空间之外,我不确定70%的填充量是多少,但我可能错了.