見出し画像

ApexとEinsteinを使い続けて見えてきたSalesforce標準機能の限界とパフォーマンスの上げ方及びSalesforce社への提案

タイトルが長い!
今回は中級者以上向けの内容です。ムツカシイネー

Salesforce、うまく使えていますか?弊社リバネスも導入から6年が経ち、試行錯誤を繰り返しながら前進している所です。その中でも、長年に渡り構築してきたオブジェクトの構造を見直し、再構築をするという大改造を終えたりもしました。

さて、なんでこんな話を書き始めたかと言うと、本日開催されていたSalesforce活用チャンピオン大会の中で「オブジェクトに作れるカスタム項目数の上限が500では少なすぎる」みたいなテーマを見かけて、確かに標準機能をフル活用する気持ちで使っているとそう思わざるを得ないという感覚になったから。

Salesforceの良い所はGUIで簡単にDB項目を増やせる所

Salesforceでの命名ですが、RDBで言う所のtableをオブジェクト、columnをカスタム項目と思ってください。

オブジェクトは例えば「商談」や「取引先」という単位でオブジェクトが設定されます。標準で提供されている商談オブジェクトにはないような情報を保存したいと考えたときにはカスタム項目を使って項目を増やしていく訳です。GUIで名前を決めて、データの型を決めます。加えて、レイアウト設定といって入力ページのどの部分にその項目を表示させるのかを設定してリリース完了。極めて簡単です。

Salesforceの標準の入力画面は1ページにつき1レコードの入力になります。ページにはレコードのIDが付与され、URLにもIDが表示されます。とてもわかり易い構造です。

新規商談__通常の商談___Salesforce

例:弊社の商談入力画面

弊社の商談オブジェクトは、導入当初から存在し、様々な形で活用してきました。その結果

商談___Salesforce

こんなふうに、カスタム項目数の上限に限りなく近い所まで行っていることがわかります。これは使い倒すと思って使っていると宿命みたいなもので仕方ないのかなとも思うのですが、昨今のEinstein導入について色々と考えていると、このような形での使い方はあってないということがわかってきます。

テーブルを横に増やしすぎない運用

上述したような使い方はわかりやすい一方で、Excel的と言いますか、データベースとしての使い方とは違うよねという事に気付きます。

例えば「検査」みたいなオブジェクトがあったとして、検査項目が1から100まであるとします。項目ごとに点数を付与する必要があり、5段階でクオリティを評価するという処理をしているとします。

標準機能で考えるオブジェクト構造はこうなります。

画像3

検査1の入力画面には、項目1から100までの入力欄が並び、それぞれに点数をつけていくという形になります。標準機能でこれを実現するにはそれしかありませんし、それで良いのです。

ただ、もしこのデータを特定の目的で集計したいとなった場合、これだとパフォーマンス的に厳しくなって来ます。

こちらで言えば、特定の期間にスコアが3以上だった検査項目がいくつあるのかという計算をしたとします。このデータ構造で考えると

項目1が3以上は何個あるか?
項目2が3以上は何個あるか?
...以下100まで繰り返す

という集計をする必要があり、データ処理にとてつもない時間がかかってしまいます。インプットは楽だけどアウトプットが難しいという状態になります。なぜかと言うとアウトプットには時間制限(ガバナ制限といいます)が設けてあり、それを超えると出力エラーになってしまうからです。データ量が増えてくると頭の痛い問題になります。

これを集計しやすい構造に変えるとこんな形になります。

画像4

横に伸びていた項目を項目名という一つのカラムにまとめ、スコアは一つのカラムでまとめます。一度の入力で100レコードを作る必要がありますが、パフォーマンス的には特に問題ないのです。

こうしておくと、すべてのレコードに対して、スコアが3以上のものの数をカウントするという検索クエリ一発で結果を取り出すことができてとてもリーズナブルだったりします。
ただ、これを標準機能の入力画面でやろうとした場合、入力を100回繰り返すことになることを意味します。それは人間側に負担が大きすぎます。

標準機能の限界はこの辺にあります。人間の入力の容易さを取るか、アウトプットをやりやすくしたいかということを天秤にかけるタイミングが来たら、No Codeでの実装は不可能です。開発者を入れて、一度で複数レコードを生成できるような入力画面を作ってもらいましょう。

Salesforce社には、ぜひ入力ページレイアウトという項目を作ってもらって、レイアウトした項目を指定した回数一括入力できるようなインターフェイスの実装を進めて欲しいなと思っています。*1,*2,*3

オブジェクトは利用目的単位で作るべし

弊社の例で言うと、社員用のオブジェクトとして

・定期面談:PRシート
・PMTMatirix
・週報
・商談コミットメント

という形で、社員用のデータが格納されるオブジェクトにも関わらず、複数のオブジェクトに分けて管理していました。一見、利用目的ごとに作られているじゃないかと思うのですが、ここで言う利用目的は「最終的なアウトプットの単位」です。

我々はこれらのデータを半期の査定面談用ダッシュボードで可視化しています。それぞれのデータには、所有者IDと、面談年月(2020-08のような形式)が入っており、それをすべて取得する処理をしていました。

つまりやり方としては

・定期面談PRシートの所有者IDがxxxの面談時期が2020-08を取得
・PMTMatirixの...以下同じ
・週報の...以下同じ
・商談コミットメントの...以下同じ

ということで少なくとも4回の検索処理が必要になります。データ量が増えることでガバナ制限を突破してしまうようになり、資料の帳票作成ができなくなってしまいました。

これも先程の例と同じです。

画像5

オブジェクトを一つにまとめ、項目名(項目の種類)のようなものでそのレコードの意味を設定します。スコアは項目名によって意味は変わりますが使う数字は同じということであれば同じ項目にまとめてしまっても良いのです。

こうすることで、OwnerIDがGeorgeで面談時期が2020-08のレコードというクエリを一つ発行すれば、関連するレコードがすべて取得できるようになります。オブジェクト数も増えず、処理も早くなって言うことないですね。

ここでのSalesforce社への提案ですが、レコードタイプごとに項目のラベルを変更できるようにしてほしいということです。上記の処理で言えば、4つのオブジェクトをまとめたのですから、4種類のレコードタイプが生まれるのが自然です。似た使われ方をする項目を統一して使い回せるのですが、ラベルの変更ができないと入力画面で混乱が生じます。これは是非検討してもらいたいです。IdeaExchangeにもpostしました。応援はこちらからお願いします。*1

データ密度を上げていくということ

なぜこんなことを考えるようになったのかというと、Einsteinの存在があります。Einsteinは現在、1つのオブジェクトを対象にした網羅的な解析を行うという仕組みになっています。そのため、複数のオブジェクトにまたがった関連するレコードがあるという形ではその力をフル活用できません。

利用目的単位と上述したのは、Einsteinに何を判定させたいかを単位とすると置き換えてもらっても構わないと思います。

弊社環境でいうと、もともとCommunity Cloudを導入して会員サイトを構築したという前段があるのですが、会員がある種の申請レコードを作成するという仕組みを作って、データの入力を促していました。企画A,B,C....と最終的には10個ほどの企画で展開をしたのですが、当然のように10個の新規オブジェクトが作られる訳です。

ただ、その申請書を見るのは人間。体裁はなるべく近い形に落とし込みたくなります。そうなると、かなり似通ったオブジェクトが10個できてしまうことに気付いたんですよね。

その後Community Cloudを引退してHeoku上に会員サイトを移行したのですが、そのタイミングに10個あったオブジェクトを一つにまとめ、レコードタイプで切り分けるというスタイルに変更をかけました。

そうすることによって、このプロジェクトに参加しそうなのはどんな人だろうか?みたいな解析をEinsteinに投げることが可能になります。企画を横断して参加するのはどんな人?のような質問も良いかもしれません。オブジェクト一つに対して様々なレコードがすべて乗っかっているという状態になるのです。これは最初に書いたような、テーブルを横に広げていくのではなく、縦にレコード数を増やしていくという方向性になります。DBを解析するにあたってはこのほうがやりやすいんですよ。

最後に

そんなわけで、かなりマニアックな話を開発者視点&Einstein champion視点で書いてみました。このへんの勘所がわかってくると、大規模なレコード数になったときにもガバナ制限に阻まれずにアウトプットデータを形成することができたり、なんならEinsteinが自動的にスコアリングしてくれたりします。

僕のモットーの一つに「機械ができることは機械にやらせる」というものがあるのですが、寝てる時間にコンピューティングパワーによって結果を導き出してもらうという使い方が僕のSalesforce活用術です。

参考になる人がいたら是非お話ししましょう。
以上、マニアックなお話でした。

*1:ということで、上述のようなことを実現しようとすると、入力画面の実装をLWCやVisualforce Pageを使ってやる羽目になる

*2:とはいえ、一回のクエリで持ってくるレコード数が1,000,000レコードを超える場合はこの実装方法だとだめになるので注意。

*3:入力用のオブジェクトと解析/output用のオブジェクトを別として考え、バッチ処理で有るべき姿に変更をかけるという運用でもよいかもしれません。




noteにはこれまでの経験を綴っていこうかと思います。サポートによって思い出すモチベーションが上がるかもしれない。いや、上がるはずです。