亚历克斯,
可以有许多原因的大量阅读,而且我相信,@乔纳森的回答将帮助,或者掩盖了问题,现在。获得大量读取的原因将是因为您缺少一些关键索引,并且/或者您的表统计信息不是最新的,或者它已关闭。
现在在像这样的大表上进行性能调整可能会很复杂,如果它被许多其他过程,视图和查询使用。因为更改任何索引都会对现在正在运行良好的其他查询产生巨大影响,但是如果表缺少任何索引,则任何更改都可能会有所帮助。需要考虑的事情,当你试图优化这样的事情是:
- 如何经常是这样的查询运行
- 当它运行的它的系统
- 什么是这个最频繁的操作 上影响其他进程表,插入或更新?
如果这个查询每天运行一次,或者很少发生,并且不影响其他进程,我可能会倾向于离开它。但是,如果这是一个运行频繁和/或影响其他进程的进程,那么您需要修复它。现在通过修复它,它可以很简单,只要添加WITH(NOLOCK)
表提示,如果您发现它阻塞,但如果它运行频繁,然后查看索引和统计信息。
如果你在这个表上有很多插入,那么任何额外的索引都会影响插入性能,但它会加速更新。然后是索引填充因子等等。我的观点是,在Sql框中进行性能调整非常复杂,并且大部分时间都需要整个图片。
所以我建议你在这里提一些提示,因为没有人知道你的系统和你一样,你可以做出一些决定,并做实验,并从中学习!启用您的查询执行计划并查看它,看看是否有任何表扫描,它们不好,并且表明缺少适当的索引,关键查找也是如此。
但看着你在这里给出的查询,并忽略了其他因素,这里是我的建议。
确保索引中包含employee_number
和course_code
的非聚簇索引。如果是Sql 2008,你可以添加一些包含的列,如果你有其他查询过滤这两列,但输出其他列。至于它们应该在指数中上升还是下降取决于你,但将它们都作为升序留下。
然后在查询,使用什么@Jonathan提出,对于小的修改(+1你!),在表中添加WITH(NOLOCK)提示。这会告诉Sql优化器在读取表时不要锁定表,但是您将能够读取脏数据。通常不是问题,除非它是一个高度事务性的表,大量的更新和插入一直在进行。
IF EXISTS(SELECT 1 FROM course_tracking WITH(NOLOCK)
WHERE employee_number = @employee_number
AND course_code = @course_code)
BEGIN
UPDATE COURSE TRACKING
END
ELSE
BEGIN
INSERT INTO COURSE TRACKING
END
此外,检查,如果你统计的数据库自动更新如果没有,创建维护作业,将一天一次更新,当服务器是最不活跃。以此为查询EXEC sp_MSForEachTable 'UPDATE STATISTICS ? WITH FULLSCAN'
来源
2011-02-15 21:57:12
Ryk
确保`course_code`和`employee_number`都编入索引。覆盖指数应该可以正常工作。 – JNK 2011-02-15 20:28:07
什么是SQL Server版本?因为SQLServer 2008为你提供了`MERGE`能力,这对于这样的upserts来说非常棒。 – Matthew 2011-02-15 20:30:16
@JNK,他不需要包括计数的id列吗? – DForck42 2011-02-15 20:37:31