Performance Implications of Database Snapshots

本文通过实验探讨了SQL Server 2005中数据库快照的数量如何影响数据修改操作的性能,包括插入、删除和更新操作。研究发现,随着快照数量的增加,这些操作的执行时间显著增长。
 

Performance Implications of Database Snapshots

Database snapshots are a new feature of SQL Server 2005. They offer a read-only, point-in-time view of a database. There have been some articles published here explaining what they are and discussing possible uses for them, but not about the performance impact of multiple snapshots, so I thought I'd take a look at that.

All examples shown here were done on a Windows XP, service pack 2 machine, running SQL Server 2005 Developer edition, RTM.

Statistics

The SQL Books Online states that performance may be decreased due to increased I/O on database snapshots. After running into a performance problem involving snapshots I decided to do some tests to see exactly how the performance of some typical operations degraded when using snapshots.

I set up a database with a sample table with 40 000 rows in it. The table had an int and a char(3000) column, ensuring that only two rows would fit onto a page. The int column was an identity and the clustered index.

For the first test, I inserted four sets of 5000 rows, taking care that each set affected different rows, and hence different pages. The database was restored from backup after each set. The first set of tests were done with no snapshots on the database. I then ran tests with one, two, three, four and five snapshots. For each, I measured how long the data modification would take and how long a subsequent checkpoint operation would take.

Likewise, I did tests where I deleted four sets of 5000 rows and updated four sets of 5000 rows, again with the database restored after each set of tests and the tests were done with differing numbers of snapshots in place

As the graphs show, the duration of the operations increases significantly as the number of snapshots that need to be updated increases.

Zoom in   |   Open in new window

Zoom in   |   Open in new window

Zoom in   |   Open in new window


From the results, it would seem as though large numbers of snapshots can seriously degrade database performance. The tests were done on a workstation, with all the files on a single drive, so the effects won't be so pronounced on a properly configured server with multiple properly configured drives, but it is still something to be watched.

While I was expecting an increase in the durations, I was not expecting a increase of this magnitude. In the case of deletes and updates, the difference in time to affect 5000 rows with no snapshots and with five snapshots is a factor of fifty!

I also did a quick test on a server (16 processor, 64 GB memory, SAN storage, SQL 2005 Enterprise SP2) to see how a number of snapshots affected delete speed on a high-powered machine. I wasn't being as careful as with the earlier experiments, but this does go to show that the performance degradation affects well-configured servers as well as desktop PCs.

I had a table with several million rows in and I was deleting 5000 at a time. 8 tests were done with each number of snapshots and the resulting times were averaged. The below graph shows how the delete time varied with the number of snapshots present.

Zoom in   |   Open in new window

A recent post by the PSS Engineers described in detail how IOs work in a snapshot, and the reason for the increase in duration.

Normally, when SQL modifies a data page, the data page is changed in memory and only the log record is hardened to disk before the transaction is considered complete.

Since snapshots do not have a transaction log, changes to the snapshot cannot be written to the log, but must be written directly to the data file. Hence, when a transaction modifies a page that must be written to a snapshot, to ensure durability the write of that page must be completed to disk before the transaction that modified the page is considered complete. This increases the number of physical disk writes that must be done during the transaction.

If the IO system that the snapshot is stored on is slow (as in my case with the initial experiment, since I was using a workstation PC), these additional writes (1 per snapshot file) can cause quite substantial slow downs in the source database.

This also explains why the checkpoint process does not show any appreciable increase in duration as the number of snapshots increases. Since the copy-on-write is done as part of the data modification statement, the checkpoint has no extra work to do.

Conclusion

While database snapshots have their uses, they are not without side-effect. Planning should be carefully done when using snapshots, especially if large numbers of snapshots are needed, or they are needed for long periods of time.

Depending on the capacities of the IO system, the extra load that the snapshots impose may be unnoticed, or it may drag the system down completely. Careful testing should be done before using them in production environments, especially in systems where fast transactions are essential.

By Gail Shaw, 2008/09/23

<think>好的,我现在需要帮助用户解决Keil5在C99标准下出现的“implicit declaration of function is invalid”错误。首先,我要回忆一下用户提供的参考资料,看看有哪些可能的原因和解决方法。 根据引用[1]、[2]、[3]、[4]的信息,这个警告通常是因为函数在被调用前没有被正确声明。用户可能没有包含相应的头文件,或者头文件中的声明有问题,或者函数的声明顺序不对,甚至可能存在宏定义冲突导致头文件未被正确包含。此外,引用[3]提到,有时函数名拼写错误也可能导致这个问题,比如下划线的数量不对。 首先,我需要列出常见的解决方法,按照用户提供的引用内容整理: 1. 检查是否包含函数声明的头文件。如果没有包含,添加#include "xxx.h"到调用函数的地方。 2. 确保头文件中的函数声明正确无误,没有拼写错误或参数不匹配。 3. 检查头文件的包含顺序,特别是如果头文件之间有依赖关系,需要先包含被依赖的头文件。 4. 查看宏定义是否重复或冲突,导致某些头文件中的声明被条件编译排除。 5. 确保函数在被调用之前已经有声明,如果函数定义在调用之后,需要在前面添加函数原型。 6. 检查函数名是否正确,比如是否有拼写错误或符号错误,例如下划线数量是否正确。 7. 更新或替换旧版本的核心文件,如core_cm3.h,确保与编译器兼容。 8. 检查项目设置,确认是否启用了C99标准,并正确配置了头文件路径。 接下来,我需要将这些步骤以清晰的结构呈现,分点说明,同时注意使用中文,并且按照用户的要求,行内数学公式用$...$,独立公式用$$...$$。不过这个问题可能不涉及数学公式,所以可能不需要使用,但需要保持格式正确。 另外,用户要求生成相关问题,我需要根据这个主题提出几个相关问题,例如关于其他常见编译错误的解决方法,如何配置Keil项目设置,或者如何处理头文件依赖等。 在回答过程中,需要引用用户提供的资料,比如引用[1]、[2]、[3]、[4],在适当的地方添加引用标识。 现在需要组织语言,确保结构清晰,步骤明确,帮助用户逐步排查问题。同时要注意使用技术术语,但保持易懂,避免过于晦涩。</think>### 解决Keil5中C99标准下的函数隐式声明警告 在Keil5中遇到`warning: implicit declaration of function "XXXX" is invalid in C99`时,此警告表示编译器未在调用函数前找到其显式声明。以下是分步解决方法: #### 1. **检查头文件包含** - **确保调用函数的源文件包含对应头文件**:若函数`func()`定义在`module.c`中,其声明应在`module.h`中,调用方需添加`#include "module.h"`[^2]。 - **验证头文件路径**:在Keil项目设置中,确认头文件目录已添加到`Include Paths`(`Options for Target -> C/C++ -> Include Paths`)。 #### 2. **验证函数声明与定义一致性** - **检查拼写与参数**:头文件中的函数声明需与定义完全一致,包括参数列表和返回值。例如: ```c // module.h void func(int a, float b); // 声明 // module.c void func(int a, float b) { ... } // 定义 ``` - **注意特殊符号**:如引用[^3]所述,若函数名包含双下划线(如`__func()`),需确保声明与定义中符号数量一致。 #### 3. **调整声明顺序** - 若函数A调用了函数B,需确保函数B的声明出现在函数A之前,或在头文件中以**前向声明**形式提前声明。例如: ```c // 前向声明 void funcB(); void funcA() { funcB(); } void funcB() { ... } ``` #### 4. **排查宏定义冲突** - 若头文件使用条件编译(如`#ifdef MODULE_ENABLED`),需检查宏是否被重复定义或未正确定义,导致声明被跳过[^1]。 - 可通过预处理后的文件(`Options for Target -> Listing -> Preprocessor Listing`)验证头文件是否被包含。 #### 5. **更新核心库文件** - 若问题涉及CMSIS等核心库(如`core_cm3.h`),检查是否为旧版本文件导致兼容性问题。可替换为Keil或IAR自带的新版本文件,并调整项目设置中的库配置[^4]。 #### 6. **显式声明未包含的函数** - 对于未封装在头文件中的函数,直接在调用前添加函数原型。例如: ```c // 显式声明 extern void func(); int main() { func(); return 0; } ``` #### 7. **验证编译器标准设置** - 在`Options for Target -> C/C++ -> Language`中,确认已启用C99模式(勾选`C99 Mode`)。 --- ### 相关问题 1. **如何避免Keil中头文件重复包含的问题?** - 使用`#pragma once`或`#ifndef HEADER_H`宏定义实现头文件保护。 2. **Keil项目中出现`undefined reference`错误应如何解决?** - 检查函数定义是否存在、链接顺序是否正确,或库文件是否缺失。 3. **C99标准下为何要求显式函数声明?** - C99禁止隐式声明以提高类型安全性,避免参数类型推断错误。 4. **如何调试Keil中的宏定义冲突?** - 使用预处理输出功能分析宏展开结果,或通过`#warning`指令跟踪宏状态。 通过上述步骤,可系统化排查并解决函数隐式声明问题。若仍存在异常,建议检查代码结构或更新开发环境版本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值