
添付ファイルを消してもディスクが空かないのはなぜ? sys_attachment_doc と DB Compaction を実機で確かめる
ストレージの使用量が警告に近づき、不要な添付を消したのに数字が減らない。ジョブを待てば戻るのか、何か手を打つ必要があるのか、迷う場面です。
削除した添付の行は、その場で消えます。ただし、テーブルが確保したディスクは手放されず、空き領域として残ります。そのため、容量の数字は減りません。
この空き領域は、次に追加された添付が先に使います。消した分だけ容量は増えにくくなりますが、容量そのものは戻りません。

起点は①の添付を入れた状態、緑は添付が使っている領域、灰色は削除で空いた領域、橙は再追加した添付
図の内容を文字でも書き出します。
① 添付を入れる:確保した領域を、添付(約2.1GB)が使っている
② 添付を全部消す:行は0件になるが、確保した領域はそのまま。空き領域が 2,024MB 残り、容量の数字は減らない
③ 約1.0GBを追加する:新しい添付は空き領域から使う。空き領域は 1,019MB に減り、容量はその分増えない
この空き領域を初期設定のまま縮めるのは、夜間ジョブの DB Compaction です。対象になるのは、回収できる量が10GB以上・回収率が50%以上などの条件を満たしたテーブルだけです。数GB規模の削除では条件に届かないため、初期設定のままでは夜間ジョブの対象になりません。
Australia の PDI に、ファイルサイズの合計で約2.1GBの添付を入れてから消し、この流れを実際に測りました。
検証環境:Australia PDI / OOTB / 2026-10-01 確認
試した規模は小さく、1インスタンス・1テーブル(sys_attachment_doc)・1サイクルです。PDI の検証用インシデント2件に、乱数で作ったファイル(40MB×5)を10回複製しました。合計は50ファイル・約2.1GB(保存形式では約2.8GB)です。
この結果だけでは、OOTB 全体や本番環境での挙動までは言えません。時刻はインスタンス表示の PDT です。
押さえておくこと
添付の行は、削除した時点で消える。ジョブを待つ必要はない
消した分は、テーブルの空き領域(reclaim)として残る。容量の数字は減らない
新しい添付は、この空き領域から先に使う
初期設定で縮めるのは夜間の DB Compaction。4つの条件を満たしたときだけ動く

②と③は、PDI でしきい値を下げ、手動で起動したときだけの結果です。初期設定のままなら、①の状態で夜間ジョブの対象になりません。
行は削除した時点で消える
削除した添付の行は、ジョブを待たずにその場で消えます。確かめた削除の経路と結果は次のとおりです。
親インシデントの削除:メタ・チャンクとも0行になった
REST の削除(20MB):1.6秒で 204 が返り、チャンクは31行から0行になった
GlideSysAttachment.deleteAttachment():50件・約2.1GBの削除に89秒かかり、チャンクは3,050行から0行になった
GlideRecord.deleteRecord() と deleteMultiple():どちらもチャンク2行が0行になった
どの経路でも、ゴミ箱のようなテーブル(sys_attachment_soft_deleted)と、掃除待ちの記録(sys_attachment_cleaner_entry)は0件のままでした。

時間がかかるのは、テーブルが確保していたディスク領域を戻すほうです。
消した分はディスクの空き領域として残る
添付の実体を持つ sys_attachment_doc は、行を削除したあとも、確保したディスクをそのまま持ち続けます。夜間ジョブの判定結果では、この領域が reclaim size(回収できる量)として表示されます。
添付を出し入れしたときの変化を、次の表に並べました。

表の内容を文字でも書き出します。
約2.1GBを追加(50ファイル):テーブルサイズ 2,210MB、空き領域 0MB、判定は Skipped
50ファイルを全削除:テーブルサイズ 3,371MB、空き領域 2,024MB(60%)、判定は Skipped
約1.0GBを再追加(25ファイル):テーブルサイズ 2,367MB、空き領域 1,019MB(43%)、判定は Skipped
25ファイルを全削除:テーブルサイズ 3,366MB、空き領域 2,018MB(59%)、判定は Skipped
しきい値を 1,024MB に下げて起動:テーブルサイズ 3,366MB から 1,009MB、空き領域 2,018MB から 5MB、判定は Completed
テーブルサイズの列は統計値なので、更新が遅れます。削除したのに増えて見えるのはこのためで、見るべきは空き領域の列です。
行は0件になったのに、2,024MB が使われないまま残りました。夜間ジョブと同じ判定を実行した結果は、「10,240MB未満」による Skipped でした。
ディスクを縮めるのは夜間ジョブ DB Compaction
初期設定でディスクを縮めるのは、スケジュールジョブの DB Compaction です。毎日21:00(インスタンス時刻)に実行され、スクリプトは new GlideTableCompactor().compact(); の1行だけです。

①の Script 欄に、実際に実行される処理が書かれています。②の Trigger type は Daily、Run time の Hours は 21 です。テーブルごとの判定結果は、sys_compaction_run に1行ずつ記録されます。
判定結果の message には、毎回同じ4つの条件が書かれています。
reclaim size (MB): expected >= 10240
reclaim percentage: expected >= 50
max row count: expected <= 100000000
max table size (MB): expected <= 102400圧縮されるのは、4つの条件をすべて満たしたテーブルだけです。削除から夜間の判定までの流れは、次の図のようになります。

起点は添付の削除、緑は実機で確認した動き、橙は空き領域が残る状態、青は夜間ジョブの判定、赤は Skipped の経路
緑の圧縮は、PDI でしきい値を下げて確認した動きです。
数GB規模の削除は、夜間ジョブの対象にならない
回収量の条件は 10,240MB(10GB)です。今回の 2,024MB は、その約5分の1でした。
初期設定のままの夜間の履歴では、sys_attachment_doc は 9/24 から 9/30 までの7日間、すべて Skipped でした。この間のテーブルサイズは 481〜485MB、reclaim は 1〜5MB です。
今回は、2GB の空き領域を夜間ジョブに任せて待つ検証はしていません。同じ日の 02:42 に手動で圧縮しました。小さな削除では回収量が10GBに届かないため、初期設定のままでは夜間の判定を通りません。
sys_properties には、glide.db.compaction.* のプロパティが1件もありませんでした。つまり、初期設定の値のまま動いています。
回収率50%の条件は、大きなテーブルほど厳しい
見落としやすいのが、回収率50%の条件です。回収できる量が、テーブル全体の半分以上必要になります。
30GBのテーブルで12GB消した場合:回収率40%で Skipped
20GBのテーブルで12GB消した場合:回収率60%で対象になる
100GBを超えるテーブル:回収率に関係なく対象外
上の3行は、message の4条件から計算した例です。実際に試したのは、本記事の1テーブルだけです。
同じ量を消しても、テーブルが大きいほど回収率は下がります。
再追加すると、空き領域から先に使われる
削除したあとに添付を足すと、空き領域が先に使われます。約1.0GB(25ファイル)を再追加したところ、reclaim は 2,024MB から 1,019MB に減りました。
削除と追加を繰り返すテーブルでは、空いた領域を次の添付が使います。
しきい値を下げると、約1分半で縮んだ(PDI だけの検証)
ここからは PDI だけで行った検証です。仕組みを確かめるために、しきい値を変えました。
外部資料に書かれていたプロパティ名で glide.db.compaction.criteria.reclaim_size_mb を作り、値を 1,024 にしました。判定の message の expected が 1,024 に変わったので、このプロパティ名は実機で有効です。そのうえで DB Compaction を手動で起動すると、sys_compaction_run に Completed の行が追加されました。

①が、圧縮が実行された行です。sys_schema_change(Table Change)にも、Alter Type が Compact Table の記録が残りました。

Online Alter はオン(実行中に添付を操作する検証はしていない)
所要時間は、画面の Duration では 1 Minute
開始と終了の時刻(02:42:18 から 02:43:54)から計算すると約1分36秒
圧縮前は 3,366MB、回収見込みは 2,018MB、行数は 22,351
圧縮後は、テーブルサイズ 1,009MB、reclaim 5MB
約2.3GB が戻りました。検証のあとで作成したプロパティを削除し、glide.db.compaction.* が0件の状態に戻しています。
添付の大きさは、数え方で値が変わる
容量の話で数字が食い違う原因の一つが、添付の大きさの数え方です。今回の50ファイルについて、3つの値を並べます。
ファイルサイズ(sys_attachment の size_bytes):合計 2,097,152,000バイト(約2,000MiB)
保存形式の大きさ(sys_attachment_doc の length の合計):2,797,064,800(約2,667MiB)
消したあとに空いたディスク(reclaim):2,024MB
保存形式は、ファイルを gzip で圧縮し、base64 の文字にしたものです。sys_attachment は compressed=true で、size_compressed は size_bytes よりわずかに大きい値でした。乱数のファイルは圧縮しても小さくならないためです。length の合計は size_bytes の約1.33倍で、base64 の 4/3 と一致します。
ディスクに空いた量は、1番目のファイルサイズに近い値でした。なお、sys_attachment_doc は圧縮形式(row_format=COMPRESSED)のテーブルです。
「消した添付の合計」と「戻る容量」を比べるときは、size_bytes で見積もると今回の結果に近くなります。reclaim の MB が10進の MB か MiB かは、message に単位の定義がないため確認できていません。
削除の前に、reclaim の見込みを出す
容量を減らす目的で添付を整理するなら、削除の前に次の順で見積もります。回収待ちの量は、sys_compaction_run を開けば分かります。
次のURLを自分のインスタンスで開く
/sys_compaction_run_list.do?sysparm_query=table_name=sys_attachment_doc^ORDERBYDESCsys_created_on
先頭の行を開き、message の reclaim size (MB) と reclaim percentage を読む
消す添付の size_bytes を合計し、今の reclaim に足す
足した値が 10,240MB 以上か、テーブルサイズの50%以上かを確かめる
判定の行は、毎日21:00(インスタンス時刻)に1行ずつ増えます。reclaim が 10,240MB に近づいているなら、次の夜の判定を見ておく価値があります。
両方の条件を満たせば、夜間ジョブが縮めます。届かない場合は、戻したい量と時期に合わせて、次の節の方法から選びます。
本番で容量を戻す方法
回収量が条件を満たすまで待つ
大量の削除を一度に行った場合は、条件を満たした夜に夜間ジョブが縮めます。条件は、reclaim が10GB以上かつ50%以上です。
ServiceNow サポートに、対象テーブルの圧縮を依頼する
ServiceNow のテクニカルサポート(パフォーマンスチーム)が、Community に記事を書いています。大量に削除したあとに圧縮が動かないときは、プロパティを自分で変えずに、NowSupport から相談するよう案内しています。急ぐなら、これが第一候補です。
Community のブログが参照している KB1518213 は、ログインが必要なサポート記事です。今回は中身を確認していません。
空き領域を再利用する前提で運用する
添付の追加が続くテーブルなら、空き領域は次の添付の保存に使われます。
しきい値のプロパティを変える
本記事の PDI で行った方法です。Community には、本番でプロパティを調整して約2TBを回収した事例も載っています。
ただし、大きなテーブルほど圧縮に時間がかかります。外部資料には、100GBを超えるテーブルで5時間以上かかった例も出てきます。本番で変える場合は、対象テーブルの大きさと実行時刻をサポートと相談して決めてからにしてください。本番でのしきい値の変更は、今回試していません。
どれを選ぶかは、「あと何GB戻したいか」と「急ぐかどうか」で決まります。迷ったら、前の節の手順で reclaim の量を確認するところから始めます。
実機で気づいたこと
table size は統計値で、reclaim のほうが削除・追加にそのまま連動する
表の 2,367MB は、再追加で行が増えた時点でも古い値のままでした。行数の列は 21,516、24,030、18,218 と変わりましたが、どの時点でも実際の行数と合っていません。更新される条件は分かっていないため、本文では reclaim を主な指標にしました。
Table Cleaner の登録がなくても圧縮された
付録の Community ブログ「Keeping your instance database footprint tidy (09)」に、圧縮の条件についての記述があります。圧縮には Table Cleaner(sys_auto_flush)への登録が必要、という趣旨です。一方で sys_attachment_doc には登録が0件で、do_optimize の属性もありません。それでも、しきい値を下げると Compact Table が実行されました。この Australia PDI では、その条件は当てはまりません。
製品同梱の説明にも、関連する記述があります。
Optimize that table at the next table cleanup regardless of the percentage of records being cleaned, unless optimize is otherwise disabled
(訳:次回のテーブルクリーンアップで、削除する行の割合に関係なく、そのテーブルを最適化する。最適化が別途無効にされている場合を除く)
これは sys_auto_flush の force_optimize 項目の説明で、引用元は /sys_documentation_list.do?sysparm_query=name=sys_auto_flush^element=force_optimize です。なお、Table Cleaner のジョブはこの PDI では Disabled でした。
容量の統計表は、この PDI では0件だった
sys_physical_table_stats には、table_size_in_gb と reclaim_estimate_in_gb の列があります。この PDI では記録が0件でした。Physical Table Stats Gatherer は毎日動いているのに、記録は出ていません。容量を確かめるなら、sys_compaction_run の message を読むのが確実でした。
削除マーク方式のジョブは、中身が return; の1行だった
名前だけ見ると、添付に削除の印を付けて後で消す仕組みがありそうです。Delete Marked Attachments と Purge Orphan Attachments という2つのスケジュールジョブがあり、実機ではどちらも active=false でした。

呼び出される Script Include の中身は return; の1行でした。description には、PRB1849752 の更新が適用されている旨が書かれています。印を付けて消す経路は、この PDI では動いていません。土曜に動く Remove Orphaned Attachments も、掃除待ちの記録が0件なので何も消しません。
検証範囲とおことわり
検証したのは Australia の PDI 1台、sys_attachment_doc の1テーブル、満杯・削除・再投入・削除・圧縮の1サイクルのみ
本番環境・大規模テーブル・複数ノードでの挙動は未確認
2GB 規模の空き領域を、初期設定のまま夜間ジョブに任せて待つ観察はしていない
Compact Table の実行中に添付を追加・削除したときの影響は未確認
しきい値を下げる操作は PDI だけで実施した。本番で行ってよいかは検証範囲外
外部資料のプロパティ名は、reclaim_size_mb の1件だけ実機で有効と確認した。ほかのプロパティは未確認
KB1518213 はサポート記事のため、中身を確認していない
Table Cleaner の登録が要るという外部資料の条件が、版によって違うかは未確認
添付一覧の画面(クリップのアイコン)からの削除は試していない。REST・スクリプト・親レコードの削除で確かめた
Table Cleaner(sys_auto_flush)で添付を消したとき、チャンクの行が残るかは未確認。この PDI では Table Cleaner のジョブが無効だった
reclaim の MB が10進の MB か MiB かは未確認
ディスクの大きさが size_bytes に近かった理由が row_format=COMPRESSED かは未確認。乱数以外のファイルでの大きさも未確認
行数の列が更新される条件は未確認
削除と追加を繰り返す本番環境で、空き領域がどう使われるかは未確認
DB は MySQL 系(glide.db.rdbms=mysql)だった。RaptorDB(PostgreSQL 系)のインスタンスでの動きは未確認
公式ドキュメントの本文は参照できなかったため、製品同梱の説明(sys_documentation の hint)と実機の結果を根拠にしている
用語
reclaim:テーブルが確保しているのに、行が使っていない領域。回収できる量
DB Compaction:reclaim が大きいテーブルを夜間に縮めるジョブ。GlideTableCompactor が処理する
Compact Table:圧縮の記録。sys_schema_change に残る
チャンク:添付の実体を分割した1行。sys_attachment_doc に保存される
付録:調査で使ったURLと外部資料
製品同梱の説明は、次のURLを自分のインスタンスで開くと、同じ記述を確認できます。
フィールドの公式説明:/sys_documentation_list.do?sysparm_query=nameINsys_compaction_run,sys_auto_flush^hintISNOTEMPTY
priority 項目の説明(確認した行の priority はすべて100):/sys_documentation_list.do?sysparm_query=name=sys_compaction_run^element=priority
判定結果の一覧:/sys_compaction_run_list.do?sysparm_query=table_name=sys_attachment_doc
圧縮の記録:/sys_schema_change_list.do?sysparm_query=alter_type=compact_table
外部資料(ServiceNow 公式ドキュメントではありません)
How can the Platform rebuild tables to reduce free space within?(ServiceNow テクニカルサポートのパフォーマンスチームによる Community 記事。サポートへの相談を案内)
Keeping your instance database footprint tidy (09): Reclaiming Table Free Space(Community ブログ。Utah で導入、KB1518213 を参照)
ServiceNow Database Compaction(whitebrick.eu。プロパティ名と既定値の一覧)
Database Compaction: UI & Experience(個人ブログ。大きなテーブルの所要時間の経験談)
Prevent having to buy extra storage by reclaiming unused storage(Community。本番でプロパティを調整した事例)
The table for attachments (sys_attachment_doc) doesn't decrease in size after attachment is deleted(Community の質問。同じ困りごと)
関連記事