私が見たテクニックの 1 つは、一種の「ハードコードされた」EAV パターンを使用することです。電話を切らないで!あなたが話していたデータセットのサイズでうまく機能し、実際には EAV を使用しませんでした - それは EAV 風でした。
アイデアは、これらのカスタム属性をその中に格納する一連のテーブルを用意し、それらにいくつかのトリガー (後述) を設定することです。カスタム属性のテーブルセットには、属性に関するメタデータが格納されます (どのテーブルと組み合わせるか、データ型、制約など)。あなたはこれで非常に空想を得ることができますが、私はその必要がありませんでした.
メタテーブルのトリガーは、DB 内のファースト クラス オブジェクトにベース + エクステンションをロールアップするビューを再生成するためにあります。したがって、テーブル person + employee 拡張テーブルの代わりに、両方を含む employee ビューがあります。カスタム属性テーブルに新しい値をドロップすると、トリガーはビューを再ロールし、新しいものを含めます。極端にやりたい場合は、トリガーにストアド プロシージャを書き換えさせることもできます。中間層のコードがどのように構造化されているかによっては、一部のコードを再コーディングする必要がありますが、データを読み取るルールを適用する場合は、いずれにせよこれが当てはまります。
テストでは、あなたが話しているレコードの数が比較的少ない場合、パフォーマンスはやや遅くなりましたが、ほぼ同じ劣化パターンに従いました (レコード数の 2 倍、〜 2 倍の速度)。
-- 編集 --
私が見た方法では、最初のクラスのオブジェクトを表すテーブルがありました。つまり、「人」の行と「従業員」の行などです。これを FCO と呼びます。次に、FCO を表すテーブルを格納するセカンダリ テーブルを作成しました。これを Srcs と呼びます。 person の場合、1 つの行があり、それが person テーブルです。Employee の場合、person テーブルと Employee 拡張の 2 つの行があります。Attribs と呼ばれる 3 番目のテーブルがあり、FCO を構成するテーブルの列を格納します。簡単にするために、Employee には ID、Name、Address があり、Employee には Hire Date と Department があり、明らかに PersonID は Person テーブルを参照しているとします。したがって、FCO テーブル (person と employee) に 2 行、Src テーブルに 3 行、Attribs に 8 行。
このビュー (vw_Employee と呼びます) は、2 つのテーブルから PersonID、Name、Address、Hire Date、Department を選択します。これは、OnMetadataChange と呼ばれる SQL ストアド プロシージャによって構築されます。
この SP は (トリガーまたはバッチ プロセスによって) 起動され、その目的は CREATE VIEW ステートメントを生成することです。すべてのファースト クラス オブジェクトを反復処理し、ビューを構成するテーブルのフィールドを収集し、それに基づいて CREATE ステートメントを発行します。そのため、OnMetadataChange はビューごとに DROP と CREATE を生成し、FCO テーブルのエントリごとに 1 回実行される動的 SQL ステートメントを生成します。トリガーでこれを行うことが望ましいですが、必須ではありません。FCO 定義があまり頻繁に変更されないことを願っています。変更された場合は、おそらくコード リリースもあるでしょう。その時点で OnMetadataChange SP を実行できます。
最終結果は 2 層データベースです。ビューは、アプリケーションにとって意味のある First Class Object レイヤーを構成します。アプリケーションはビューのみを使用します。テーブルは、アプリケーションが気にする必要のない「物理」レイヤーを構成します。メタテーブルは基本的に、FCO レイヤーと物理レイヤーの間のマッピングです。セットアップには時間がかかりますが、非常に効果的であり、EAV の多くの利点を提供すると同時に、3nf テーブルの具体的な利点 (インデックス可能性など) を提供します。
必要に応じて、サンプル SQL を公開できます。