大量データを扱う際のクイックtips...
DESCRIPTION
TRANSCRIPT
大量データを扱う際のクイックTips - カスタムインデックス & スキニーテーブル編 -
2014/1/15 株式会社セールスフォース・ドットコム
Corporate Pres ‒ PowerPoint Template ‒ 4x3 FY14.pptx
2
Safe Harbor Statement Safe harbor statement under the Private Securities Litigation Reform Act of 1995: This presentation may contain forward-‐‑‒looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-‐‑‒looking statements we make. All statements other than statements of historical fact could be deemed forward-‐‑‒looking, including any projections of subscriber growth, earnings, revenues, or other financial items and any statements regarding strategies or plans of management for future operations, statements of belief, any statements concerning new, planned, or upgraded services or technology developments and customer contracts or use of our services.
The risks and uncertainties referred to above include -‐‑‒ but are not limited to -‐‑‒ risks associated with our new business model; our past operating losses; possible fluctuations in our operating results and rate of growth; interruptions or delays in our Web hosting;
breach of our security measures; the immature market in which we operate; our relatively limited operating history; our ability to expand, retain, and motivate our employees and manage our growth; risks associated with new releases of our service; and risks associated with selling to larger enterprise customers. Further information on potential factors that could affect the financial results of salesforce.com, inc. are included in our registration statement (on Form S-‐‑‒1) and in other filings with the Securities and Exchange Commission. These documents are available on the SEC Filings section of this Web site.
Salesforce.com, inc. assumes no obligation and does not intend to update these forward-‐‑‒looking statements.
Any unreleased services or features referenced in this or other press releases or public statements are not currently available and may not be delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently available.
3
はじめに
• 本ドキュメントは、大量(100万件以上)のレコードをForce.com上で扱う際に有用になりうる施策についてまとめています。
• 実際のチューニングはワークフロー・トリガの有無、データの分布等、複合的な要因に依存しますので、あくまで参考としてご利用下さい。
• パフォーマンスチューニングに限らず、その他開発者向けの質問は、ディスカッションボードをご利用下さい。 Discussion Forums日本語 https://developer.salesforce.com/forums/?communityId=09aF00000004HT8IAM
カスタムインデックス
5
Salesforceのインデックス
• クエリー(リストビュー、レポート、SOQL)の処理性能を向上させるためのインデックスが使用できる場合がある • 標準インデックス
• 次の項目に自動的に作成される
• カスタムインデックス • 標準インデックス対象外の任意の項目に、必要に応じて作成する • ただし次に挙げるデータ型の項目には作成できない
Id Name OwnerId RecordTypeId CreatedDate Systemmodstamp
(LastModifiedDate) Division Email
(取引先責任者とリード) 参照関係項目と主従関係項目
複数選択リスト ロングテキストエリア リッチテキストエリア 暗号化テキスト 非決定性の数式 (詳細は後述)
6
2つのカスタムインデックスの作成方法
1. 項目を「外部ID」または「ユニーク」として定義 • 外部ID項目とユニーク項目には自動的にカスタムインデックスが作成される • 外部ID指定が可能なデータ型
• 自動採番、メール、数値、テキスト • ユニーク指定が可能なデータ型
• メール、数値、テキスト
2. Salesforceテクニカルサポートに作成をリクエスト • オブジェクト定義、データ分布、クエリーの条件等を元に、インデックスの有効性がチェックされる
• インデックスの作成オプションを指定する必要がある場合がある • Null値もインデックスに含めるかどうか
• “Field__c = NULL”という条件のクエリーがあり、かつ、NULL値が少数の場合に有効
• チェックボックス項目の場合、True(チェック)とFalse(非チェック)のどちらをインデックスに含めるか
• 少数(通常は10%以下、少なくとも20%以下)しか存在しないほうの値のみをインデックス化する
7
2カラムカスタムインデックス • インデックスは単一の項目だけでなく、2つの項目の組合せに対しても作成することができる
• 2つの項目に対する組合せで絞り込み条件が指定される場合や、1つ目の項目で絞り込み(WHERE句)、2つ目の項目でソート(ORDER BY)する場合に有用
• 2カラムカスタムインデックスは、先頭項目のみの単一項目インデックスとしても利用できる
• Field1__c(選択リスト)とField2__c(数値)の2カラムカスタムインデックスが有効な例
• SELECT … FROM MyObject__c WHERE Field1__c IN (‘Foo’, ‘Baa’) AND Field2__c > 0
• SELECT … FROM MyObject__c WHERE Field1__c IN (‘Foo’, ‘Baa’) ORDER BY Field2__c
• SELECT … FROM MyObject__c WHERE Field1__c = ‘Foo’
8
数式に対するインデックス (1/2) • 数式項目にインデックスを作成するには、「決定性の」数式である必要がある
• 以下のいずれかに当てはまる数式は「非決定性」と見なされ、インデックスは作成できない
• 直接、間接に他オブジェクトの項目を参照している • 常に同じ値を返すとは限らない関数 (TODAY や NOW など) を使用している • 所有者、自動採番、ディビジョン、監査項目 (CreatedDateとCreatedByID以外)を参照している
• インデックス付けできない項目(複数選択リストなど)を参照している • マルチ通貨組織における通貨項目を使用している • 特殊な機能を持つ以下の標準項目を参照している
• 商談 : Amount、TotalOpportunityQuantity、ExpectedRevenue、IsClosed、IsWon
• ケース : ClosedDate、IsClosed • 商品 : ProductFamily、IsActive、IsArchived • ソリューション : Status • リード : Status • 活動 : Subject、TaskStatus、TaskPriority
9
数式に対するインデックス (2/2) • 非決定性の数式での絞り込みが効果的な場合の回避策
• 非数式のカスタム項目を定義し、インデックスを作成 • トリガーなどを使って、数式の結果の値をその項目にコピーする
• 3つ以上の項目に対する条件の組合せで効率的に絞り込める場合の応用例
• 元のクエリーの検索条件 : WHERE Field1__c = ‘A’ AND Field2__c = ‘B’ AND Field3__c = ‘C'
• 3つの条件は単独ではそれぞれ3分の1ずつしか絞り込めないとする • どの2項目の組合せで2カラムカスタムインデックスを作成しても、9分の1にしか絞り込めない
• 解決策 : 数式による実質的な「3カラムカスタムインデックス」 • Field1__c + ‘¦’ + Field2__c + ‘¦’ + Field3__c のような数式項目Formula__cを定義し、カスタムインデックスを作成
• クエリーの条件を “WHERE Formula__c = ‘A¦B¦C’ に書き換える
10
インデックスが使用されない条件 • インデックスによる選択性が低い
• 詳細は次ページ
• 比較方法が「一致しない」「!=」「NOT IN」 • 可能なら結果が変わらないように比較方法を逆転させる
• Checkbox__c != FALSE → Checkbox__c = TRUE • チェックボックス項目の例
• Picklist__c NOT IN (‘A’, ‘B’) → Picklist__c IN (‘C’, ‘D’) • A, B, C, Dの4つのオプションを持つ選択リストの例 • データにNullが含まれる場合は結果が変わりうる点に注意
• Nullを含まないインデックスが作成された項目で、比較方法が「= NULL」
• 中間一致/後方一致検索 • 中間一致: 「次の文字列を含む」, Text__c LIKE ‘%Foo%’ • 後方一致: Text__c LIKE ‘%Foo’
• 数値、日付、日付/時間以外の項目での範囲検索
11
インデックスの選択性(1/2) • 標準インデックス
• 条件を満たすレコードが以下のしきい値以下の場合に「選択性が高い」 • レコード全体のうち、最初の100万件までは30% • レコード全体のうち、100万件を超える分の15% • 最大で100万件
• しきい値の算出例 • 総計50万件 → 50万件 × 30% = 15万件 • 総計250万件 → 100万件 × 30% + 150万件 × 15% = 52万5000件 • 総計600万件 → 100万件 × 30% + 500万件 × 15% = 105万件 → 100万件
• カスタムインデックス • 条件を満たすレコードが以下のしきい値以下の場合に「選択性が高い」
• レコード全体のうち、最初の100万件までは10% • レコード全体のうち、100万件を超える分の5% • 最大で333,333件
• しきい値の算出例 • 総計50万件 → 50万件 × 10% = 5万件 • 総計250万件 → 100万件 × 10% + 150万件 × 5% = 17万5000件 • 総計600万件 → 100万件 × 10% + 500万件 × 5% = 35万件 → 333,333件
12
インデックスの選択性 (2/2) • AND結合
• インデックス化項目に対する2つ以上の条件がAND結合されている • 各インデックスを2倍のしきい値で選択性の高低判定 • 選択性の高い全てのインデックスの「積」を満たすレコード数がしきい値以下なら、それら全てのインデックスが使用される
• 全てが標準インデックスなら、標準インデックスのしきい値 • 1つでもカスタムインデックスが含まれるなら、カスタムインデックスのしきい値
• OR結合 • インデックス化項目に対する2つ以上の条件がOR結合されている
• 例: WHERE Field1__c = ‘Foo’ OR Field2__c = ‘Baa’ • 全ての条件項目に選択性が高いインデックスが存在し、かつ、各条件を満たすレコードの「和」がしきい値以下なら、それら全てのインデックスが使用される
• 全てが標準インデックスなら、標準インデックスのしきい値 • 1つでもカスタムインデックスが含まれるなら、カスタムインデックスのしきい値
• AND結合も含まれるような複雑なクエリーの場合、Salesforceテクニカルサポートを通じてインデックスの有効性を確認する必要がある
13
インデックスに関するその他の注意事項 • インデックスが増えるにつれ、レコードの更新性能は劣化する
• カスタムインデックスの作成は必要最小限にとどめる
• 本番組織で定義したカスタムインデックスは、サンドボックスにもコピーされる • ただし、インデックス作成時点で既に存在するサンドボックスについてはリフレッシュが必要
• リフレッシュしない場合や、サンドボックス→本番、サンドボックス→サンドボックスの場合、組織別にカスタムインデックスの作成をリクエストする
• スキニーテーブルを使用している場合 • ベースオブジェクトのインデックスをスキニーテーブルにもコピーするかどうかは、スキニーテーブル作成依頼時にサポートへリクエスト
• スキニーテーブル作成後に、ベースオブジェクトにカスタムインデックスを追加作成する場合も同様
14
参考資料 • 大量のデータを使用するリリースのベストプラクティス
• http://wiki.developerforce.com/page/JP:Documentation
• Maximizing the Performance of Force.com SOQL, Reports, and List Views • http://blogs.developerforce.com/engineering/2013/07/maximizing-the-performance-of-force-com-soql-reports-and-list-views.html
• Force.com SOQL Best Practices: Nulls and Formula Fields • http://blogs.developerforce.com/engineering/2013/02/force-com-soql-best-practices-nulls-and-formula-fields.html
• Webinar: Inside the Force.com Query Optimizer • http://wiki.developerforce.com/page/Webinar:_Inside_the_Force.com_Query_Optimizer_(2013-Apr)
スキニーテーブル
16
スキニーテーブルとは (1/3)
• 特定オブジェクトの一部の項目のみでコンパクトに構成されたデータベーステーブル • 一部の標準オブジェクト(取引先、取引先責任者、商談、リード、ケース)と、カスタムオブジェクトに対して作成可能
• ベーステーブルの一部の項目と全てのレコードを持つ • ベーステーブルとスキニーテーブルのデータは常に同期される • ベーステーブルにある論理削除レコード(「ごみ箱」内のレコード)は含まれない
• 主に大量のレコードを含むオブジェクトに対するクエリー(レポート、リストビュー、SOQL)の性能を向上させるために利用される
17
スキニーテーブルとは (2/3)
• クエリー実行時にスキニーテーブルにアクセスするかどうかは、Salesforceのクエリーオプティマイザーが決定する • スキニーテーブルを機能させるには、少なくとも、クエリーが参照する全ての項目がスキニーテーブルに含まれる必要がある
• 対象オブジェクトの持つ項目のうち、100項目までをスキニーテーブルに含められる • 数式項目は不可
• ただしクエリーに含まれる数式項目が参照する項目が、全てスキニーテーブルに含まれれば、スキニーテーブルを使用することは可能
• 他オブジェクトの項目も不可 • 主従関係項目、参照関係項目を含めることは可能 • この場合、参照先オブジェクトにもスキニーテーブルが存在すれば、スキニーテーブル同士のジョインとなる可能性もある
• 項目数は少ないほうが性能が得られやすい
18
スキニーテーブルとは (3/3)
• インデックス • ベーステーブルのインデックスをスキニーテーブルにもコピーするかどうかは、スキニーテーブル作成依頼時にサポートへ依頼
• スキニーテーブル作成後に、ベースオブジェクトにカスタムインデックスを追加作成する場合も同様
• 通常のSalesforceユーザーからは一切見えない • Salesforceテクニカルサポートが依頼を受けて設定
• 有効性が認められる場合のみ作成される • 通常ユーザーはスキニーテーブルの定義も存在自体も確認することはできない
• ソーステーブルとのデータ同期も自動的に行われる
19
クエリー性能が悪化する理由 • ベーステーブルの内部データ構造
• 標準オブジェクト • オブジェクト毎に標準項目用とカスタム項目用の2つのテーブル(組織IDでハッシュパーティショニング)があり、全てのユーザー組織のデータは同じテーブルに保持される
• カスタムオブジェクト • 全てのユーザー組織の全てのカスタム オブジェクトのデータは、組織IDで ハッシュパーティショニングされた 単一のテーブルに保持される
• 性能向上を妨げる要素 • 標準オブジェクトの場合、標準項目とカスタム項目の両方を参照するクエリーでは、SQLレベルでテーブルジョインが発生する
• カスタム項目が多いとレコード長が長くなりストレージ効率が悪くなる • 1回のブロックリードで取得できるレコード数が少ない、さらには1レコード取得するのに複数回のブロックリードが必要となる場合もある
• アクセスの少ない項目がキャッシュされるため、キャッシュヒット率が低くなる • 大量レコードに効率アクセスには工夫が必要
• オブジェクトのレコードへは必ずインデックスアクセス(組織IDとオブジェクトID)が必要(注1) • 膨大なアクセスレコード数のためフルスキャンは非現実的
• 論理削除レコードも含まれる
注1 : 全てのテーブルへの直接アクセスはいかなる場合も不可となっており、セキュリティが担保されたインタフェースを介してのみ アクセスが許可され、組織毎のデータの安全性が確保されている
20
スキニーテーブルでクエリー性能が向上する理由 • スキニーテーブルのデータ構造
• 1つのスキニーテーブルには、特定組織の特定オブジェクトのデータのみが保持される • 標準項目とカスタム項目の区別はなく、スキニーテーブル作成時に指定された項目に対応する列のみで構成される
• 性能が向上する理由 • テーブルジョインが減る
• 標準オブジェクトの標準項目とカスタム項目の両方にジョインなしでアクセス可 • ストレージ効率が良い
• レコードがコンパクトなので、1ブロックに含まれるレコード数が多くなる • 1回のブロックリードでより多くのレコードを取得できる • 同量の消費メモリで、より多くのレコードをキャッシュできる
• インデックスもコンパクト • テーブルは特定オブジェクトのデータしか保持しないので総レコード数が少ない • 組織IDとオブジェクトIDを含まないのでキーが短く、ブロック当たりキー数が増える • その結果Bツリーインデックスの高さが低く抑えられ、インデックスアクセス時のI/Oが減る
• 論理削除レコードを含まない
• テーブルフルスキャンができる • 自社組織以外のレコードが含まれないので、クエリーでインデックスが利用できない場合には、フルスキャンが効率的になる
• フルスキャンはシーケンシャルリードなので、大量データの読み取りに向いている
21
スキニーテーブルの注意事項
• 新規作成したカスタム項目をスキニーテーブルにも追加するには、Salesforceサポートに再作成を依頼する必要がある
• スキニーテーブル項目の定義を変更すると、スキニーテーブルが無効化されるので、Salesforceサポートに再作成を依頼する必要がある
• サンドボックスにはコピーされない • 必要に応じてSalesforceサポートに別途リクエストする
22
参考資料
• 大量のデータを使用するリリースのベストプラ クティス • http://wiki.developerforce.com/page/JP:Documentation
• Long- and Short-Term Approaches for Tuning Force.com Performance • http://blogs.developerforce.com/engineering/2013/03/long-and-short-term-approaches-for-tuning-force-com-performance.html
• Force.com のマルチテナントアーキテクチャ • http://wiki.developerforce.com/page/JP_Multi_Tenant_Architecture
• Webinar: Inside the Force.com Query Optimizer • http://wiki.developerforce.com/page/Webinar:_Inside_the_Force.com_Query_Optimizer_(2013-Apr)