大量データをCSVファイルでエクスポートする方法

Yuki21
Tera Expert

お世話になっております。
テーブルに格納されているレコードを全件CSVファイルでエクスポートするための手段について質問させてください。

①リスト表示後、「列のオプション」を右クリックし、エクスポート>CSVを選択
②https://<インスタンス名>.service-now.com/<テーブル名>_list.do?CSV

上記2つ以外の方法はありますでしょうか?
上記の方法ですと処理時間がタイムアウトしないようなレコード数のデータのみエクスポート可能な認識です。
タイムアウトするような大量レコードのエクスポートはServiceNowが推奨していないことは認識しておりますが、
テーブルデータバックアップの要件として挙がっており、対策をご存知であればご教示いただければと思います。

1 ACCEPTED SOLUTION

iwai
Giga Sage

バックアップ目的であれば、CSVファイルよりXMLファイルで保存するべきです。
復元するときXMLファイルインポートなら完全に元のレコードに戻ります。
復元するときに取り込める最大数の制限を受けるので、巨大なファイルを復元できません。
そのため、大量データのExport方法は、1万件程度に分割してDownloadします。

補足、バックアップであればReferenceしているテーブル(ユーザー関連など)もすべてバックアップをしておきましょう。(Reference先のSYSIDを正しく参照できるようにXMLファイルで関連テーブルすべてをバックアップする)

単純に今回だけデータを手動でバックアップしたい要件であれば、下記のようなScriptで分割ダウンロードのURLを作成できます。Script Backgroundで実行してみてください。インスタンス名など各種パラメーターは環境に合わせて変更してください。

var myInstance = 'myInstance'; // インスタンス名
var myTable = 'incident'; // エクスポートテーブル名
var myQuery = ''; // エクスポートQuery 必要な場合に記載
var myFileType = 'CSV'; // エクスポート形式 CSV,XLSX,UNL(UNL=XML形式でダウンロード)
var setLimit = 10000; // エクスポート分割行数
var sysid = '';
var exportUrl = [];
var gr = new GlideRecord(myTable);
gr.initialize();
var fields = gr.getFields();
var myField = [];
var num;

exportUrl.push('https://' + myInstance + '.service-now.com/' + myTable + '_list.do' +
    '?sysparm_query=' +
    (!!myQuery ? encodeURIComponent(myQuery) + '%5EORDERBYsys_id' : 'ORDERBYsys_id') +
    '&sysparm_record_count=' + setLimit +
    '&sysparm_default_export_fields=all&' + myFileType);
num = setLimit - 1;
do {
    gr = new GlideRecord(myTable);
    gr.initialize();
    if(myQuery) gr.addEncodedQuery(myQuery);
    gr.orderBy('sys_id');
    gr.chooseWindow(num, num + 2);
    gr.query();
    if (gr.next()) {
        sysid = '' + gr.getValue('sys_id');
        exportUrl.push('https://' + myInstance + '.service-now.com/' + myTable + '_list.do' +
            '?sysparm_query=sys_id%3E' + sysid +
            (!!myQuery ? '%5E' + encodeURIComponent(myQuery) : '') +
            '%5EORDERBYsys_id' +
            '&sysparm_record_count=' + setLimit +
            '&sysparm_default_export_fields=all&' + myFileType);
    }
    num += setLimit;
} while (gr.next());
for (num = 0; num < exportUrl.length; num++) {
    gs.info(exportUrl[num]);
}

 

定期的に自動バックアップをしたいなら、バックアップするサーバー側にPowershellやPythonなどで、定期的に分割ダウンロードするScriptを組むと良いです。もし要望があれば投稿します。

View solution in original post

11 REPLIES 11

iwai様

ご返信ありがとうございます。
スクリプトのご連携につきましてもありがとうございます。

大量データの場合、分割してダウンロードする方法が推奨されていることも理解いたしました。
数億件のレコードを退避することを想定していたのですが、方針そのものを見直す方向で検討したいと思います。

参考までにお聞きしたいのですが、URIの中のORDERBYはsys_idのみ指定可能でしょうか?
別の項目(日付)を指定するようにしたらレスポンスなしになりました。

  • 質問『URIの中のORDERBYはsys_idのみ指定可能』
  • 回答、今回の分割ダウンロードの仕組みとしてはsys_idのみ指定可能です、指定しても順序は変わらないです。Queryの機能としては複数指定可能です。
    例:incident_list.do?sysparm_query=active%3Dtrue%5EORDERBYpriority%5EORDERBYopened_at%5EORDERBYcaller_id
    incident_list.do?sysparm_query=active=true^ORDERBYpriority^ORDERBYopened_at^ORDERBYcaller_id

分割ダウンロードの仕組みとしては、sys_id(重複の無い値)でソートすることで分割しています。重複する値では正確な数量で分割できません。重複しない値でソートした後では、他のソートを付け足しても、順序が変わる余地はありません。

例:3つごとに分割する例。sys_idは重複しないので、他のソートを付け足しても順序は変わらない。

Linesys_idCount
1a1
2b2
3c3、ここで分割
4d1、sys_id>cのQuery条件でデータ取得するのでここから始まる
5e2
6f3、ここで分割

数億件のレコードの退避に耐えられるか検証したことがないので、実際に1000万件ぐらいの分割数でダウンロード可能かどうか、確かめてみてください。XMLの最大数(下の図の設定)も1000万件やそれ以上に設定して正しくダウンロードできるか確かめてみてください。

find_real_file.png

(追記、XML最大数のプロパティーには”com.glide.processors.XMLProcessor.max_record_count”と言うものもあるようなので、設定してみてください。Export Limits: Beyond the 50K - Support and Troubleshooting (servicenow.com) )

XMLダウンロードの場合、URLのパラメーターを”UNL”にすると即時ダウンロードできます。参考例のScriptにも記載しておきました。(例myFileType = 'UNL')ブラウザで”XML”を指定した場合は、最初にブラウザ画面にXMLが表示されてダウンロードが始まらないです。”UNL”にすると即時ダウンロードできます。

iwai様

ご回答ありがとうございます。

大変参考になりました。

kaka_1234
Tera Contributor

こちら、サーバー側に書くスクリプトはどのようなものになるか、だけでもよいのでご教授いただけないでしょうか?

晃敏池
Tera Contributor

te