Causes and Countermeasures for Disk I/O Performance Degradation After Migrating an On-Premises SQL Server to AWS
公開日 2026-09-07 · 更新日 2026-09-07 · 最終検証日 2026-09-07
結論
On-premises physical servers use PCIe bus-attached local NVMe/SSD with extremely low latency and high I/O throughput, but Amazon EBS, the standard for AWS RDS/EC2, is a virtual block storage attached via network, with IOPS and throughput strictly throttled according to instance size and volume type. Without understanding this difference, batches and index rebuilds stall due to throttling even when CPU headroom exists, and oversizing Provisioned IOPS only increases costs without addressing the root cause. The basic approach is to reduce the volume of disk I/O itself, with buffer pool maximization, data compression, physical separation of data and log files, and addressing CDC cleanup delays causing log bloat as the practical center of these efforts.
この文書の適用条件
| 対象製品 | SQL Server (Amazon RDS for SQL Server / SQL Server on EC2) |
|---|---|
| 確認バージョン | SQL Server 2012 and later (CDC-supported editions vary by version; verify) |
| 適用環境 | AWS migration from on-premises physical servers (Amazon RDS for SQL Server, EC2) |
| 必要権限 | Read-only commands require VIEW DATABASE STATE or equivalent. db_owner (or sysadmin depending on environment) for manually running sys.sp_cdc_cleanup_job and executing DBCC SHRINKFILE |
| 実行影響 | Read-only commands only query. sp_cdc_cleanup_job deletes CDC change data; DBCC SHRINKFILE changes log file size |
| 再起動 | Not required |
| 最終検証日 | 2026-09-07 |
そのまま実行できるコマンド
- 対象
- SQL Server 2008 or later / Amazon RDS for SQL Server
- 権限
- reference permission on the target table (execute permission for sp_estimate_data_compression_savings)
- 変更作業
- none (estimate only, does not perform actual compression)
- Production実行
- allowed
-- Target: SQL Server 2008 or later / Amazon RDS for SQL Server
-- Permission: reference permission on the target table (execute permission for sp_estimate_data_compression_savings)
-- Change: none (estimate only, does not perform actual compression)
-- Production execution: allowed
USE [SampleDB];
GO
EXEC sys.sp_estimate_data_compression_savings
@schema_name = 'dbo',
@object_name = 'Orders',
@index_id = NULL,
@partition_number = NULL,
@data_compression = 'PAGE';The difference between size_with_current_compression_setting and size_with_requested_compression_setting in the results indicates the estimated disk space reduction from compression. Compression reduces disk I/O at the cost of CPU overhead, so it is more effective in environments with CPU headroom.
- 対象
- SQL Server 2008 or later / Amazon RDS for SQL Server
- 権限
- metadata visibility on sys.databases
- 変更作業
- none (read-only)
- Production実行
- allowed
-- Target: SQL Server 2008 or later / Amazon RDS for SQL Server
-- Permission: metadata visibility on sys.databases
-- Change: none (read-only)
-- Production execution: allowed
SELECT name, log_reuse_wait_desc
FROM sys.databases
WHERE name = 'SampleDB';
-- If the result is 'REPLICATION', CDC or transactional replication is holding unread logsREPLICATION can apply to both CDC and transactional replication. Check whether CDC is enabled on the target database with sys.databases.is_cdc_enabled. For details on tracking capture delays, see "How to check whether the CDC log scan has stopped in SQL Server".
- 対象
- SQL Server 2008 or later (CDC-supported editions) / Amazon RDS for SQL Server
- 権限
- db_owner (execute permission for cdc.sp_cdc_cleanup_job)
- 変更作業
- yes (deletes data from CDC change tables beyond the retention period)
- Production実行
- allowed, but verify that downstream integrations are not still consuming the data to be deleted
-- Target: SQL Server 2008 or later (CDC-supported editions) / Amazon RDS for SQL Server
-- Permission: db_owner (execute permission for cdc.sp_cdc_cleanup_job)
-- Change: yes (deletes data from CDC change tables beyond the retention period)
-- Production execution: allowed, but verify that downstream integrations are not still consuming the data to be deleted
USE [SampleDB];
GO
EXEC sys.sp_cdc_cleanup_job;This is an immediate workaround when the scheduled cleanup job is delayed. However, this addresses the symptom, not why the cleanup job itself became delayed (job stoppage, insufficient runtime, etc.) — investigate separately. Before executing, always confirm that replication targets or downstream ETL processes have not yet read change data within the retention period.
- 対象
- SQL Server 2008 or later / Amazon RDS for SQL Server
- 権限
- sysadmin or db_owner
- 変更作業
- yes (truncates the end of the log file to reduce its size)
- Production実行
- generally allowed, but only after confirming log_reuse_wait_desc is NOTHING
-- Target: SQL Server 2008 or later / Amazon RDS for SQL Server
-- Permission: sysadmin or db_owner
-- Change: yes (truncates the end of the log file to reduce its size)
-- Production execution: generally allowed, but only after confirming log_reuse_wait_desc is NOTHING
USE [SampleDB];
GO
-- specify target size in MB to shrink to
DBCC SHRINKFILE (N'SampleDB_log', 1024);Shrinking before resolving the log_reuse_wait_desc cause will result in immediate re-expansion. In this knowledge base, all SHRINK operations are marked as "high" regardless of impact level. For the difference between data file and log file shrinking and how to use TRUNCATEONLY, see "The difference between DBCC SHRINKDATABASE and DBCC SHRINKFILE, and what to check before running them".
結果の読み方
| 列 | 意味 | 確認するポイント |
|---|---|---|
| log_reuse_wait_desc | Reason why transaction log space is not being released | 'REPLICATION' indicates CDC or transactional replication is holding unread logs. 'NOTHING' means there is no factor preventing release |
| size_with_requested_compression_setting | Estimated size after applying the specified compression type | The larger the difference from the current size, the greater the potential for disk I/O reduction and storage cost savings |
こういう状況で使います
- Nightly batches and index rebuilds take two or more times longer, even with an AWS instance of equivalent or higher spec than the on-premises server before migration
- The entire database becomes temporarily unresponsive during large-scale data loads or index rebuilds
- Batches never complete despite CPU having available capacity
- Storage capacity sharply depletes shortly after migration, triggering frequent RDS auto-storage scaling
- Increasing Provisioned IOPS (io2, etc.) only drives up storage costs without achieving fundamental improvement
考えられる原因(可能性の高い順)
01
Latency inherent to network-attached storage (EBS)
On-premises physical NVMe/SSD is directly attached via the PCIe bus and operates with microsecond-level latency, but Amazon EBS, the standard for AWS RDS/EC2, is a virtual block storage connected to the instance via a dedicated internal network link. Physical latency (in the order of milliseconds) is structurally unavoidable.
02
IOPS and throughput throttling (bandwidth limiting)
IOPS and throughput (MB/s) limits per second are strictly defined according to instance size, volume type, and allocated capacity. General-purpose volumes such as gp2/gp3 consume burst credits when exceeding the baseline performance, and reaching limits during large-scale data loads or index rebuilds causes severe throttling that can make the entire DB unresponsive. Even raising volume-side IOPS with io2 or similar may be bottlenecked by the instance-side EBS dedicated bandwidth (EBS-Optimized).
03
Cost inflation from oversizing Provisioned IOPS
When attempting to easily resolve insufficient I/O performance by heavily provisioning high-cost IOPS types such as io2/io2 Block Express, storage costs alone can balloon to hundreds of thousands to millions of yen per month, eliminating the cost-reduction benefits of cloud migration.
04
Unreleased logs due to CDC cleanup job delay
When large batch updates occur and the CDC cleanup job cannot keep up, the transaction log is marked as "not yet read by CDC," preventing log space from being released even after CHECKPOINT or log backups. The log file continues auto-extending, depleting storage capacity and forcing RDS auto-storage scaling to trigger.
確認手順
- 1
Estimate compression space reduction for existing tables
参照のみUse sys.sp_estimate_data_compression_savings to determine how much disk I/O reduction and storage cost savings potential exists.
- 2
Identify the cause of unreleased logs with log_reuse_wait_desc
参照のみCheck whether sys.databases.log_reuse_wait_desc is fixed at REPLICATION. If so, CDC or transactional replication delay is suspected.
- 3
Check whether CDC is enabled and if capture is delayed
参照のみVerify CDC status with sys.databases.is_cdc_enabled. If enabled, check capture delay with sys.dm_cdc_log_scan_sessions (see the related article for details).
- 4
Verify EBS volume and instance IOPS/throughput contracted values
参照のみCheck the provisioned IOPS and throughput for the volume type (gp3/io2, etc.) and the EBS bandwidth limit on the instance side via the AWS console or CLI.
- 5
Manually execute CDC cleanup
中After confirming that downstream integrations have consumed all data within the retention period, execute sys.sp_cdc_cleanup_job to restore the log to a releasable state.
- 6
Shrink the transaction log
高After confirming log_reuse_wait_desc is NOTHING, shrink the log file to the target size using DBCC SHRINKFILE.
対応方法
すぐに実施できる低リスクの対応
Maximize the buffer pool to reduce disk reads
低Before paying to increase storage IOPS, scale up the instance size to increase RAM and maximize the SQL Server buffer pool size. Maintaining a state where frequently accessed active data remains cached in memory greatly alleviates the EBS I/O bottleneck.
Manually execute CDC cleanup to clear unreleased logs
中Execute sys.sp_cdc_cleanup_job without waiting for the scheduled job, restoring the log to a releasable state. Verify downstream integrations have consumed the data before executing.
事前検討が必要な変更
Separate data files and log files onto different EBS volumes
中Mixing data files (random I/O dominant) and transaction logs (sequential writes dominant) on the same EBS volume causes I/O queue contention. Always separate them onto different EBS volumes.
Apply PAGE/ROW compression to reduce I/O volume
中When CPU resources are available, data compression reduces the block size read from disk and the size written to the log. Estimate the effect with sp_estimate_data_compression_savings before applying.
Offload read load with a read replica
中If reporting queries and batch reads are straining the primary DB I/O bandwidth, build a read-only replica to distribute traffic.
Add CDC cleanup job lag to monitoring
低Monitor the success/failure and duration of the cleanup job to detect before the delay becomes chronic.
再起動・サービス影響を伴う変更
Shrink the transaction log with DBCC SHRINKFILE
高Execute after confirming log_reuse_wait_desc is NOTHING. Shrinking without resolving the cause will result in immediate re-expansion. The operation consumes I/O during execution, slowing writes to the target.
専門家のレビューが必要な作業
Redesign the need for Provisioned IOPS (io2, etc.) across the entire workload
専門家レビュー必須Consider this only when IOPS remain insufficient even after buffer pool maximization, data compression, and file separation. Unplanned increases significantly raise monthly costs — have the I/O pattern of the entire workload analyzed and undergo professional review.
!注意事項
- Before running DBCC SHRINKFILE, confirm that log_reuse_wait_desc is NOTHING. Shrinking while the cause remains will result in immediate re-expansion.
- Before deleting CDC change data beyond the retention period with sys.sp_cdc_cleanup_job, verify that downstream integrations (replication targets or ETL) have not yet consumed data from that period.
- Before casually increasing Provisioned IOPS (io2, etc.), first evaluate whether reducing disk I/O itself through buffer pool maximization and data compression is feasible.
- The compression ratios and cost savings figures in this article depend on the workload and data content and are not guaranteed for all environments.
これで解決しない場合に確認すること
Have you checked whether EBS volume IOPS/throughput burst credits are exhausted?
Verify that gp2/gp3 burst credit balance has not been depleted using CloudWatch metrics.
Have you checked whether the instance-side EBS bandwidth (EBS-Optimized) is the bottleneck?
Even raising volume-side IOPS will not produce expected performance if the instance EBS dedicated bandwidth limit has been reached.
Have you checked the CDC cleanup job execution history and errors?
Verify that the cleanup job regularly succeeds and that there are no consecutive failures or skips in the job history.
Have you measured network latency including whether AWS Direct Connect is needed?
Verify that communication latency between on-premises remaining applications and the DB on AWS is not another bottleneck.
この文書の根拠と限界
実運用で確認した内容
This article generalizes Amazon EBS IOPS/throughput specifications, SQL Server CDC and DBCC SHRINKFILE public specifications, and trends commonly observed across multiple similar migration cases. Specific numerical values for compression ratios and cost savings are environment-dependent estimates and do not include specific customer examples or internal issue numbers.
よくある質問
Is slow disk I/O after AWS migration always an instance sizing mistake?
Not necessarily. On-premises physical NVMe/SSD and AWS network-attached storage (EBS) have fundamentally different structures, and even selecting an equivalent-spec instance results in performance limits due to IOPS and throughput throttling. First consider designs that account for this structural difference: buffer pool maximization, file separation, and compression.
Does increasing Provisioned IOPS (io2, etc.) solve the problem?
It may solve the problem in some cases, but costs tend to escalate rapidly. We recommend first maximizing the buffer pool to reduce disk reads, then reducing I/O volume with data compression, and only considering IOPS increases if those measures are still insufficient.
Is the same response appropriate when log files are enlarging even though CDC is not in use?
log_reuse_wait_desc becoming REPLICATION can apply to both CDC and transactional replication. First check whether CDC is enabled with sys.databases.is_cdc_enabled. If CDC is not in use, refer to the transaction replication configuration or general log file usage verification procedures.
When is it safe to run DBCC SHRINKFILE?
When log_reuse_wait_desc has become NOTHING. If CDC cleanup delay is the cause, first execute sys.sp_cdc_cleanup_job to make the log releasable. Data file shrinking and log file shrinking have different impacts, so review the related articles before proceeding.
この文書がカバーする質問
- I want to know the cause of slowdown after migrating on-premises SQL Server to AWS
- I want to know why storage costs surged after AWS migration
- I want to know how to handle log files that keep growing due to CDC
リスク表示の意味
- 参照のみデータと設定を変更しません。
- 低影響は限定的ですが、権限と負荷の確認が必要です。
- 中性能・ロック・コストに影響する可能性があります。
- 高障害・データ損失・復旧作業が発生する可能性があります。
- 専門家レビュー必須本番適用前に別途レビューが必須です。
GIIPの対応範囲
Alerts based solely on resource threshold values such as "Disk I/O exceeds 90%" cannot reveal which queries or processes are causing the I/O pressure or how much unnecessary cost is actually being incurred per month. GIIP retains storage I/O, IOPS consumption, CDC cleanup job execution status, and log file changes in the same time series, enabling root causes to be identified on a cost ($) basis. Decisions that are irreversible and high-cost, such as Provisioned IOPS increases, are operated on the basis of having a human confirm the SQL and rollback procedures to be executed beforehand.
執筆・技術検証
GIIP プロダクション運用チーム
大規模Webサービス、SQL Server、Oracle、AWS、Azureの設計・移行・運用に約30年従事。x12largeクラスのAWS RDS for SQL Server環境12セット、約12万テーブルのOracle環境、約3TBのTiDBからAurora MySQLへの移行を経験。現在も複数のクラウドデータベースと約30のWebサービスを、AIエージェントと人間の専門家が継続的に監視・運用しています。
関連サービス
Diagnose disk I/O performance after an AWS migration
同じ確認を複数の環境で継続する必要がある場合は、運用体制ごと相談できます。
Diagnose disk I/O performance after an AWS migration