移行業務の改善 その3 CSV加工の分離
はじめに
弊社では ecforce
というシステムをSaaSという形でサービスを提供しています。
ecforceの導入を希望されるクライアント様には、大きく2パターンがあります。
-
新規で
ECを立ち上げたいというクライアント様 - 別のカートシステムを現在使っており、ecforceに乗り換えたいというクライアント様
後者につきまして、当然ながら顧客や注文データをリセットするわけにもいかないので、 既存データも引き継ぎたい
という要望をいただくことが大多数です。
ただ他社のカートシステムとecforceではデータ構造が異なるので、データを抽出してそのままecforceのデータベースにインポートできるわけではありません。
この後者の要望を叶えるためにはデータを
- 抽出し
- 加工した上で
- ecforceのデータベースにインポートする
という手順を踏む必要があります。
これを社内では 移行業務
と呼んでおり、弊社にはこの移行業務を行う専門チームがあります。
本題
SQLの高速化と並列処理の導入によって、スクリプト自体は速くなりました。
ただ、移行業務のさらなる高速化を検討していたことに加え、案件によってスクリプトを実装しなければならない点についても課題感を持っていました。
ecforceのバックエンドはRailsに依存していたため、データのインポートも同様、Railsのモデルクラスへの依存を切り離せないと判断しました。
ただし データの加工については、インポート処理と分離できるのではないか
という仮説を立てました。
データの加工を分離させるにあたり、以下4つを重要視しました。
- Rubyスクリプトよりも高速であること
- コストが安いこと
- 案件によるイレギュラーな加工でも自分たちでコントロールできること
- ノーコードツールを実現することで単純な処理にエンジニア工数を使わないようにすること
サービスやツールを探したところ、AWSの Glue
や DataBrew
を見つけました。
コストとイレギュラー対応がネックになり、導入には至らなかったものの、DataBrewの レシピ
という概念に触れました。
これは データの加工をするための簡単な関数を組み合わせで使えば、やりたいことはだいたい満たせる
といったものです。
このDataBrewの レシピ
という考え方に基づいて、移行業務におけるデータ加工を、PythonのCSVライブラリ Pandas
で独自で実装することにしました。
実例
文章だけだと伝わりづらいので、実例を用いて説明します。
移行元CSV
商品名 | 商品カテゴリ名 | 商品コード | 定期商品かどうか | 販売価格 |
---|---|---|---|---|
Tシャツ | アパレル | A3831448FD | いいえ | 2000 |
プロテイン | 健康食品 | D1530E86DF | はい | 1500 |
パーカー | アパレル | DDD71B95A4 | いいえ | 3000 |
加工したCSV
name | product_category_id | number | is_recurring | sales_price |
---|---|---|---|---|
Tシャツ | 1 | A3831448FD | false | 2000 |
プロテイン | 2 | D1530E86DF | true | 1500 |
パーカー | 1 | DDD71B95A4 | false | 3000 |
例えば上記 移行元CSV
を 加工したCSV
に変換するには、以下の手順を踏むことで実現できます。
- 商品名の列を
name
という名前でコピー - 商品カテゴリ名を実際のIDにマッピングして
product_category_id
にコピー - 商品コードの列を
number
という名前でコピー - 定期商品かどうかを「はい」だったらtrue、「いいえ」だったらfalseにし、
is_recurring
という名前でコピー - 販売価格の列を
sales_price
という名前でコピー - name, product_category_id, number, is_recurring, sales_price に絞り込み
これを レシピ
化すると、以下のようになります。
{
"steps": [
{
"action": {
"operation": "copy",
"parameters": {
"sourceColumn": "商品名",
"targetColumn": "name"
}
}
},
{
"action": {
"operation": "map",
"parameters": {
"sourceColumn": "商品カテゴリ名",
"targetColumn": "product_category_id",
"map": {
"アパレル": "1",
"健康食品": "2"
}
}
}
},
{
"action": {
"operation": "copy",
"parameters": {
"sourceColumn": "商品コード",
"targetColumn": "number"
}
}
},
{
"action": {
"operation": "map",
"parameters": {
"sourceColumn": "定期商品かどうか",
"targetColumn": "is_recurring",
"map": {
"はい": 1,
"いいえ": 0
}
}
}
},
{
"action": {
"operation": "copy",
"parameters": {
"sourceColumn": "販売価格",
"targetColumn": "sales_price"
}
}
},
{
"Action": {
"Operation": "remain",
"Parameters": {
"targetColumns": "[\"name\",\"product_category_id\",\"number\",\"is_recurring\",\"sales_price\"]"
}
}
}
]
}
これを各案件ごとに実装することで、先程挙げた4つの条件
- Rubyスクリプトよりも高速であること
- コストが安いこと
- 案件によるイレギュラーな加工でも自分たちでコントロールできること
- ノーコードツールを実現することで単純な処理にエンジニア工数を使わないようにすること
を満たすことができました。
また高速化については、
- スクリプトのみ
- レシピ + スクリプト
の両者を比較したところ、半分くらいの時間で移行業務を終えられるようになりました。
実測値では、スクリプトのみで6時間、レシピ + スクリプトで3-4時間くらいです。
まとめ
今回は移行業務のさらなる高速化/効率化を目指し、 データの加工とインポートを切り離し
ました。
さらに レシピ
という概念を取り入れて、データの加工そのものを高速化しました。
次回はデータの加工とインポートの実行環境の課題に触れつつ、コンテナ化について解説していきます。
SUPER STUDIOの採用について
SUPER STUDIOでは、エンジニアを採用しています。
少しでも興味がありましたら、以下をご覧ください。
昨年12月に9期目を迎えたSUPER STUDIOのキックオフイベントで社内表彰されたエンジニア受賞インタビュー記事です。よりSUPER STUDIOのエンジニア組織を理解できる内容となっておりますので、ご一読ください。
Discussion