69

動的論理データベーススキーマにストレージを提供するために推奨されるアーキテクチャは何ですか?

明確にするために:システムが、本番環境でユーザーによってスキーマが拡張または変更される可能性のあるモデルにストレージを提供する必要がある場合、これを可能にする優れたテクノロジー、データベースモデル、またはストレージエンジンは何ですか?

説明するためのいくつかの可能性:

  • 動的に生成されたDMLを介したデータベースオブジェクトの作成/変更
  • 多数のスパース物理列を含むテーブルを作成し、「オーバーレイされた」論理スキーマに必要な列のみを使用する
  • 動的な列の値を行として格納する「長くて狭い」テーブルを作成します。このテーブルは、特定のエンティティのすべての値を含む「短くて広い」行セットを作成するためにピボットする必要があります。
  • BigTable /SimpleDBPropertyBagタイプのシステムを使用する

実社会での経験に基づく回答をいただければ幸いです。

4

16 に答える 16

38

あなたが提案していることは新しいものではありません。多くの人がそれを試しました...ほとんどの人は、「無限の」柔軟性を追求し、代わりにそれよりもはるかに少ないものになることに気づきました. これはデータベース設計の「ローチ モーテル」です。データは入ってきますが、それを取り出すことはほとんど不可能です。あらゆる種類の制約のコードを記述して概念化してみてください。そうすれば、私の言いたいことがわかるでしょう。

最終的な結果は、通常、デバッグ、保守がはるかに難しく、データの一貫性の問題に満ちたシステムになります。常にそうであるとは限りませんが、多くの場合、そのようになります。主な理由は、プログラマーがこの列車事故が来るのを見ておらず、それに対して防御的なコードを作成できていないためです。また、多くの場合、「無限」の柔軟性は実際にはそれほど必要ではありません。開発チームが「まあ、彼らがここにどんな種類のデータを入れようとしているのかわからないので、何でも入れさせてください」という仕様を取得すると、それは非常に悪い「におい」です...そしてエンドユーザーは大丈夫です使用できる定義済みの属性タイプを持っている (一般的な電話番号をコード化する、

非常に優れた開発チームがあり、この設計で克服しなければならない問題をよく認識している場合は、ひどくバグの多いシステムではなく、適切に設計されたシステムをうまくコーディングできます。ほとんどの時間。

しかし、なぜあなたに対して非常に多くのオッズを積み上げて始めるのですか?

信じられない?Google の「One True Lookup Table」または「Single Table Design」。いくつかの良い結果: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10678084117056

http://thedailywtf.com/Comments/Tom_Kyte_on_The_Ultimate_Extensibility.aspx?pg=3

http://www.dbazine.com/ofinterest/oi-articles/celko22

http://thedailywtf.com/Comments/The_Inner-Platform_Effect.aspx?pg=2

于 2008-09-16T00:11:10.353 に答える
20

MSSQLで強く型付けされたxmlフィールドが機能しました。

于 2008-09-15T20:05:56.463 に答える
17

他の人が言ったように、他に選択肢がない限り、これをしないでください。これが必要になる 1 つのケースは、ユーザーがカスタム データを記録できるようにする必要がある既製の製品を販売している場合です。私の会社の製品はこのカテゴリに分類されます。

顧客にこれを許可する必要がある場合は、いくつかのヒントを次に示します。 - スキーマの変更を実行するための堅牢な
管理ツールを 作成し、これらの変更が他の方法で行われないようにします。 - 管理機能にする。通常のユーザーにアクセスを許可しないでください。 - すべてのスキーマ変更に関するすべての詳細をログに記録します。これは問題をデバッグするのに役立ちます。また、顧客が愚かなことをした場合、CYA データも提供されます。

これらのことをうまく行うことができれば (特に最初のもの)、あなたが言及したアーキテクチャのいずれかが機能します。私の好みは、データベース オブジェクトを動的に変更することです。これにより、カスタム フィールドに格納されたデータにアクセスするときに、DBMS のクエリ機能を利用できるようになります。他の 3 つのオプションでは、大量のデータを読み込んでから、データ処理のほとんどをコードで行う必要があります。

于 2009-11-19T17:12:58.737 に答える
9

同様の要件があり、スキーマのないMongoDBを使用することにしました。

MongoDB (「humongous」から) は、C++ プログラミング言語で記述された、オープン ソース、スケーラブル、高性能、スキーマフリー、ドキュメント指向のデータベースです。(ウィキペディア)

ハイライト:

  • 豊富なクエリ機能を備えています (おそらく SQL DB に最も近い)
  • 本番対応 (foursquare、sourceforge で使用)

Lowdarks (mongo を正しく使用できるように理解する必要があるもの):

于 2010-09-26T18:33:43.090 に答える
7

リレーショナル DB を持つことの要点は、データの安全性と一貫性を維持することです。ユーザーにスキーマの変更を許可した瞬間に、データの整合性が失われます...

CMS シナリオなど、異種データを格納する必要がある場合は、XSD によって検証された XML を行に格納することをお勧めします。もちろん、パフォーマンスと簡単な検索機能は失われますが、それは良いトレードオフです。

2016 年なので、XML は忘れてください。JSON を使用して、適切に型指定された列をバックエンドとして非リレーショナル データ バッグを格納します。通常、 bag 内の値でクエリを実行する必要はありません。これは、多くの最新の SQL データベースが JSON をネイティブに理解していても遅くなります。

于 2008-09-15T20:09:12.650 に答える
7

私は実際のプロジェクトでそれを行いました:

データベースは、50 の配列である 1 つのフィールドを持つ 1 つのテーブルで構成されていました。これには、「単語」インデックスが設定されていました。すべてのデータは型がないため、「単語インデックス」は期待どおりに機能しました。数値フィールドは文字として表され、実際の並べ替えはクライアント側で行われていました。(必要に応じて、データ型ごとに複数の配列フィールドを使用することも可能です)。

論理テーブルの論理データ スキーマは、テーブル行の「タイプ」(最初の配列要素) が異なる同じデータベース内に保持されていました。また、同じ「タイプ」フィールドを使用したコピー オン ライト スタイルの単純なバージョン管理もサポートされていました。

利点:

  1. 列を動的に再配置および追加/削除できます。データベースのダンプ/リロードは必要ありません。新しい列データは、ゼロ時間で (仮想的に) 初期値に設定される可能性があります。
  2. すべてのレコードとテーブルが同じサイズであるため、断片化は最小限に抑えられ、パフォーマンスが向上する場合があります。
  3. すべてのテーブル スキーマは仮想です。任意の論理スキーマ構造が可能です (再帰的またはオブジェクト指向であっても)。
  4. これは、「一度だけ書き込み、ほとんど読み取り、削除しない/削除済みとしてマークする」データに適しています (ほとんどの Web アプリは実際にそのようなものです)。

短所:

  1. 全語のみの索引付け、略語なし、
  2. 複雑なクエリは可能ですが、パフォーマンスがわずかに低下します。
  3. お好みのデータベース システムが配列と単語インデックスをサポートしているかどうかによって異なります (これは PROGRESS RDBMS で実装されています)。
  4. リレーショナル モデルは、プログラマーの頭の中にあるだけです (つまり、実行時のみ)。

そして今、私が考えている次のステップは、そのようなデータベースをファイル システム レベルで実装することです。それは比較的簡単かもしれません。

于 2008-09-15T21:30:12.237 に答える
3

あなたが本当に欲しいのは、実際のデータを格納するための柔軟なスキーマを記述できるデータベーススキーマである、ある種の「メタスキーマ」であるように思えます。動的なスキーマの変更は厄介であり、特にユーザーが変更を許可されている場合は、混乱させたくないものです。

このタスクに最も適したデータベースを見つけることはできないため、他の基準に基づいてデータベースを選択することをお勧めします。たとえば、DB をホストするためにどのプラットフォームを使用していますか? アプリは何語で書かれていますか? 等

「メタスキーマ」の意味を明確にするために:

CREATE TABLE data (
    id INTEGER NOT NULL AUTO_INCREMENT,
    key VARCHAR(255),
    data TEXT,

    PRIMARY KEY (id)
);

これは非常に単純な例であり、ニーズに合わせてより具体的なものがある可能性があります (そして、うまくいけば、もう少し簡単に操作できます) が、私の要点を説明するのに役立ちます。データベース スキーマ自体は、アプリケーション レベルでは不変であると考える必要があります。構造上の変更はすべてデータに反映される必要があります (つまり、そのスキーマのインスタンス化)。

于 2008-09-15T20:11:07.920 に答える
3

質問に示されているモデルは、あらゆる生産システムで使用されていることを知っています。私が勤務する大規模な大学/教育機関では、かなり大きなものを使用しています。彼らは、多くのさまざまなデータ取得システムによって収集されたデータをマッピングするために、特に細長いテーブル アプローチを使用します。

また、Google は最近、内部データ共有プロトコルであるプロトコル バッファをコード サイトを通じてオープン ソースとしてリリースしました。このアプローチをモデルにしたデータベース システムは、非常に興味深いものになるでしょう。

以下を確認してください。

エンティティ属性値モデル

Google プロトコル バッファ

于 2008-09-15T20:14:06.587 に答える
3

2 つのデータベースを作成する

  • DB1 には静的テーブルが含まれ、データの「実際の」状態を表します。
  • DB2 は、ユーザーが望むように自由に使用できます。ユーザー (またはあなた) は、DB1 から奇妙な形のテーブルにデータを入力するコードを作成する必要があります。
于 2008-09-16T15:25:59.343 に答える
2

EAV アプローチが最良のアプローチだと思いますが、コストが高くつきます

于 2011-09-16T13:55:48.933 に答える
2

古い話題であることは承知していますが、決して現実性を失うことはないと思います。そんなものを今開発中です。これが私のアプローチです。MySQL、Apache、PHP、および Zend Framework 2 をアプリケーション フレームワークとして使用するサーバー設定を使用していますが、他の設定でも同様に機能するはずです。

これは簡単な実装ガイドです。これからさらに自分で進化させることができます。

効果的な SQL は複雑すぎるため、独自のクエリ言語インタープリターを実装する必要があります。

例:

select id, password from user where email_address = "xyz@xyz.com"

物理データベースのレイアウト:

Table 'specs': (データ アクセス レイヤーにキャッシュする必要があります)

  • id: 整数
  • 親 ID: 整数
  • 名前: varchar(255)

テーブル「アイテム」:

  • id: 整数
  • 親 ID: 整数
  • spec_id: 整数
  • データ: varchar(20000)

表「仕様」の内容:

  • 1、0、「ユーザー」
  • 2、1、「メールアドレス」
  • 3、1、「パスワード」

テーブル「items」の内容:

  • 1、0、1、''
  • 2、1、2、「xyz@xyz.com」
  • 3、1、3、「私のパスワード」

独自のクエリ言語での例の翻訳:

select id, password from user where email_address = "xyz@xyz.com"

標準 SQL に変換すると、次のようになります。

select 
    parent_id, -- user id
    data -- password
from 
    items 
where 
    spec_id = 3 -- make sure this is a 'password' item
    and 
    parent_id in 
    ( -- get the 'user' item to which this 'password' item belongs
        select 
            id 
        from 
            items 
        where 
            spec_id = 1 -- make sure this is a 'user' item
            and 
            id in 
            ( -- fetch all item id's with the desired 'email_address' child item
                select 
                    parent_id -- id of the parent item of the 'email_address' item
                from 
                    items 
                where 
                    spec_id = 2 -- make sure this is a 'email_address' item
                    and
                    data = "xyz@xyz.com" -- with the desired data value
            )
    )

仕様名から spec_id を取得するには、仕様テーブルを連想配列またはハッシュ テーブルなどにキャッシュする必要があります。それ以外の場合は、次のスニペットのように、名前から spec_id を取得するために、さらに SQL オーバーヘッドを挿入する必要があります。

悪い例です。これを使用しないでください。これを避け、代わりに specs テーブルをキャッシュしてください!

select 
    parent_id, 
    data 
from 
    items 
where 
    spec_id = (select id from specs where name = "password") 
    and 
    parent_id in (
        select 
            id 
        from 
            items 
        where 
            spec_id = (select id from specs where name = "user") 
            and 
            id in (
                select 
                    parent_id 
                from 
                    items 
                where 
                    spec_id = (select id from specs where name = "email_address") 
                    and 
                    data = "xyz@xyz.com"
            )
    )

アイデアが得られ、そのアプローチが実現可能かどうかをご自身で判断していただければ幸いです。

楽しみ!:-)

于 2014-03-05T19:53:23.437 に答える
0

過去に、オプション C を選択しました。動的な列の値を行として格納する「長くて狭い」テーブルを作成し、それをピボットして、特定のエンティティのすべての値を含む「短くて広い」行セットを作成する必要があります。. しかし、私はORMを使用していたので、本当に面倒でした。たとえば、LinqToSql でそれを行う方法が思い浮かびません。フィールドを参照するには、ハッシュテーブルを作成する必要があると思います。

@Skliwz: 彼は、ユーザーがユーザー定義フィールドを作成できるようにすることにもっと関心があると思います。

于 2008-09-15T20:12:29.333 に答える
0

これは非常に古い投稿であり、過去 11 年間で多くの変更が加えられたことは承知していますが、将来の読者に役立つかもしれないので、これを追加すると思いました。私の共同創設者と私が HarperDB を作成した理由の 1 つは、完全なインデックス機能を提供しながら、単一の重複しないデータ セットで動的スキーマをネイティブに実現することです。詳細については、
https ://harperdb.io/blog/dynamic-schema-the-harperdb-way/ をご覧ください。

于 2020-09-02T17:23:01.517 に答える
-5

SQL には、スキーマを変更する方法が既に用意されています: ALTER コマンドです。

ユーザーが変更することを許可されていないフィールドをリストしたテーブルを作成し、ALTER の適切なインターフェイスを記述します。

于 2008-09-15T20:16:13.100 に答える