エンティティフレームワークとパフォーマンス、2回目の試行

Entity Frameworkのパフォーマンスの穴を塞ぐ最初の試みでは、実体化のみを検討しました。 しかし、作業の過程で、予想されるように、さらに重要な別の制限に遭遇しました。 レコードの挿入、変更、削除の操作も遅くなります。 100個の挿入の場合、EFは100個の挿入要求をグループ化せずにデータベースに送信します。



さらに、プロジェクトの1つで、1つの不快なエラーが発見されました。EFバージョン5.0.0では、Oracleを使用している場合、Clob / Xmlフィールドに2000文字を超える行を挿入できません。



ソリューションのために、次の機能を備えたコンテキスト項目と呼ばれるコンポーネントが作成されました。



1)Bulk Insert(MS Sql):主キーとしてIDを持たないテーブルでは、Ms Sql ServerデータベースでサポートされているBulk Insertメソッドを使用して挿入できます。 Identityの場合、Bulk Insertを使用して挿入するときにデータベースによって生成されたキーを確実に取得する方法はありません。したがって、そのようなキーを持つテーブルでは、いくつかの通常のInsertクエリを1つのクエリにグループ化します。 これは、一括挿入よりも大幅に遅くなりますが、EFよりも高速です。



2)シーケンスされた一括挿入(MS SQL):通常、GUIDはIDの代替であり、挿入の問題を解決しますが、別の問題を作成します-キーの長さが長いため、結合操作の動作が遅くなります。 この問題の解決策として、MS Sql Server 2012以降では、Sequenceを使用して主キーを作成できます。 これにより、整数シリアルキーを使用できるようになります。これにより、Identityと同様にクラスター化インデックスを使用でき、同時に挿入に一括挿入を使用できます。 コンポーネントは、増分1の非周期的シーケンスのみをサポートします。



3)Bulk Update(MS Sql):それ自体では、このような操作はデータベースに存在せず、コンポーネントは次の4つの操作を順番に実行することでそれを実装します。

    a)ターゲットテーブルと同じフィールドセットを持つ一時テーブルが作成されます
    b)データを一時テーブルに一括挿入します。
    c)Join-Update操作が実行され、一時テーブルのレコードからターゲットテーブルのレコードにデータが転送されます。 
      一致する主キー。
    d)一時テーブルが削除されます 


操作はアトミックではないため、トランザクションで実行することをお勧めします。



4)一括削除(MS SQL):一括更新と同様に、この操作は4つのステップで実行されます。

    a)ターゲットテーブルのプライマリキーに一致する一連のフィールドを持つ一時テーブルが作成されます
    b)削除するエントリの一時主キーテーブルに一括挿入します。
    c)Join-Delete操作が実行されます
    d)一時テーブルが削除されます


5)マテリアライゼーション:以前のバージョンから移行された機能に加えて、マテリアライゼーションのパフォーマンスとmicro-ORM Dapperの比較を含むテストプロジェクトをリポジトリに追加しました。 Context Itemsは、この操作をDapperよりも約3〜5%高速で実行し、AsNoTrackingを使用するとEFよりも40%高速で実行します。



6)配列バインドの挿入、更新、削除(Oracle):ODP.Netに実装された一括挿入コンポーネントは、トリガーや制約、さらには主キーを考慮しません。 したがって、テーブルに直接挿入するのには適していません。 また、トランザクションをサポートしていません。 もちろん、MSSqlの場合のように一時テーブルを使用することもできますが、Oracle自体が推奨する方法を使用することにしました。 このメソッドは配列バインディングと呼ばれます。 要するに、データベースに送信されるリクエストは、1つのレコードを挿入しているように見えますが、フィールドのセットをパラメーターとしてではなく、フィールド配列のセットとして渡しているため、1つのレコードだけでなく、レコードの配列を挿入、更新、または削除しています。 ここでメソッドについて読むことができます。



7)平等メンバー:主キーと連携するGetHashCodeおよびEqualsメソッドがすべてのエンティティに対して生成されます。



コンテキストアイテムコンポーネントは、EFバージョン5.0.0〜6.1.3、およびOracleおよびMS Sql Serverデータベースをサポートします。

データベース優先アプローチのみがサポートされています。制限があります-エンティティ名はテーブル名と一致する必要があります。 手は、この制限を修正するために手を伸ばしませんでした。



コンポーネントは、識別子contextitemsmssqlおよびcontextitemsoracleを使用してnuget.orgで公開されます。 GitHub.comのリポジトリでインストールと使用について詳しく読むことができます: github.com/repinvv/ContextItems



All Articles