教授は、リレーショナルテーブルを定義する代わりに、シリアル化されたJavaオブジェクトをblobとして保存するように指示しました


21

私の教授は、正しい属性でテーブルを実際に定義する代わりに、次のようにオブジェクトをIDにマップできると言っています。

id (int)  |   Serialized Object (blob)
   1               10010110110

これには多くの問題があります。データの冗長性、IDを個別に追跡する必要があり、テーブル全体をメモリにプルして何かを検索する必要があり、** Javaコードでモデルを変更したい場合は、そのモデルにデータベース。

私はそのモデルに永遠にこだわっているか、モデルを変更するために他の本当にいことをしなければなりません。私は教授に反対することを正当化しますか?私が考えていないことをこれを行うにはいくつかの利点がありますか?私が正しいなら、これについて私の教授に何か言うべきですか?彼はこれを私のクラス全体に説教し、プロジェクトをそのように構築したとさえ言っていました。セカンドオピニオンは素晴らしいでしょう。

コースの名前はSoftware Designです。

私の教授は、これが最良の方法であるとは言いませんでしたが、リレーショナルテーブルを定義するための正当な代替手段であると言いました。

モデルは決して動的ではありません。


コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
ポールホワイトはGoFundMonicaを言う

回答:


34
  1. それ自体、悪いことではありません-まったく。適切なコンテキスト(正確な要件)なしで「どちらが良い」と主張するのは無駄です。

  2. 太字の部分が間違っています。すでにシリアル化されたオブジェクトを簡単に拡張して新しいフィールドを追加し、古いオブジェクトとの完全なバイナリ互換性を実現できます。元のクラスを変更する代わりに、新しいクラスを作成することもできます。

教授との議論は、抽象的な「ベターネス」ではなく、さまざまなシナリオでの「リレーショナル」対「キーバリューストア」の長所と短所に焦点を当てる必要があります。または、クリスマスが感謝祭よりも優れているかどうかについて議論することもできます。

-他の回答を読んだ後の編集。

他の答えの1つは、「プロがデメリットを上回る場合を想像するのは難しい」と述べている限りです。

全体の議論は具体的な問題についてでなければならないので(そうでなければ「より良い」と「より悪い」を定義することさえできません)、具体的な例を挙げましょう。完全に構成されていますが、できる限り詳細に肉付けしようとしました。

さまざまなオンラインゲーム(ブラウザでプレイ、GWTで記述、javascriptにクロスコンパイル)のプレイヤーの統計情報を保存するデータベースを備えたオンラインゲームサイトがあるとします。一部のゲームは戦略的で、一部はアクションゲーム、一部はプラットフォーマーです。データベースはリレーショナルであり、プレイヤーとプレイの履歴およびスコアを保存します。

ある日、追加の要件があります:プレーヤーがゲーム中にゲームの状態をクラウドに保存し、後で同じ時点でゲームを再開できるようにします。言うまでもなく、この一時的な状態を保存する唯一の理由はゲームに戻ることであり、状態自体は決して内省されません。

2つの基本的な選択肢があります。

  • ゲームはJavaで記述されているため、モデルを簡単に取得してサーバーに送信し、1行のコードでシリアル化してblobとして保存できます。テーブルは「saved_games」と呼ばれ、プレーヤーへの外部キーなどがあります。データベースの観点から見ると、「セーブゲーム」は不透明で不可分なブロブです。

  • 100個のゲームごとに個別のリレーショナルモデルを作成できます(これはゲームごとに数十個のテーブルになります)。たとえば、pacmanの場合、食べられていないすべてのペレットの位置、ボーナス、位置、ゴーストの現在の状態を保存するテーブルが必要になります。誰かがいつかゲームを少しでも変更した場合、リレーショナルモデルを更新する必要があります。また、ゲームの種類ごとに、Javaモデルをデータベースに書き込み、それを読み戻すためのロジックを実装する必要があります。

Justin Caveの答えは、2番目のオプションを選択する必要があると言っています。これは大きな間違いだと思います。

また、ジャスティンケイブの認識では、上記で提示したのは「エッジ」または「レア」なケースであるという考えがあります。彼が何らかのハードデータを提示できない限り(たとえば、米国のエンタープライズアプリケーションだけでなく、世界中のすべてのITプロジェクトの代表的なサンプリングに基づいて)、このような意見は予測の典型的なケースだと思います。バイアス。

実際、リレーショナルデータベースでシリアル化されたJavaオブジェクトの問題は、見かけよりもはるかに深刻です。それは1NFのまさに核心に触れています。つまり 、属性の領域とは何ですか?。このトピックに本当に興味がある場合は、CJ Dateの「Date on Database:Writings 2000-2006」にすばらしい記事があります。


コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
ポールホワイトはGoFundMonicaを言う

22

このようなことをするプロジェクトを人々が成功裏に配信することができますか?残念ながら、はい、彼らはかなり頻繁にそうします。

これは良いアプローチですか?いいえ、ちがいます。基本的に、比較的高価なデータベースを使用して、比較的遅いファイルシステムに変換します。オブジェクトをシリアライズおよびデシリアライズして状態を保存するシステムを本当に構築したい場合は、データベースを使用するのではなく、ファイルシステムを使用することもできます。

データベースにオブジェクトをシリアル化してデータを保存するシステムを構築する場合、DBAと友達になることはありません。冗長データを保存することになります。共有データが更新されるたびに、一部のオブジェクトは新しい値になり、一部のオブジェクトは古い値になります。データに関するあらゆる種類のレポートを作成することを不可能にします。データを使用したい人は誰でも、追加のコードを書く必要があります。ほとんどの企業では、あるシステムからデータを抽出して別のシステムにロードしたり、複数のフロントエンドアプリケーションからレポートを配信できるレポートシステムを作成したりすることを望んでいるため、これは非常に大きな問題です。さらに、指摘しているように、あなたは常に問題に対処する必要があります。

このアプローチには利点がありますか?アプリの最初のバージョンを実装するのは非常に簡単だと主張できると思います。また、開発者は、データベースとの適切な対話に関連するものを完全に無視できます。これらの利点がアプローチの多くの欠点を上回る多くのケースを想像するのは困難です。

この特定の教授をどのように扱うべきかについては、それは別の問題です(そしておそらくこのフォーラムの範囲外の問題です)。教授が現実の世界でプロジェクトを積極的に開発している場合、彼のアプローチは根本的に間違っているという学生からの議論を恐らく受け入れないでしょう(アプローチが根本的に間違っているとしても)。教授が望む方法でプロジェクトを行い、自分で(または別のコースで)データを保存する適切な方法を学習する方が良いでしょう。


2
あなたが言ったことに加えて、私の2セント。再利用性とは、モジュール性と共有に関するものです。オブジェクトモデルは、オブジェクトの共有とコードの再利用に重点を置いています。データベースモデルは、データの共有と再利用に重点を置いています。どちらのモデルも完全にモロニーではありません。どちらのモデルも完璧ではありません。そして、この2つを調和させることは非常に困難です。
ウォルターミッティ14年

1
私はこれに同意しますが、教授が何かを教えて、それに直面することなくそれがより良い方法だと言うのを見るのは嫌です。これが正しい方法であると考えて、実世界に入るクラスの他のすべての貧しい学生はどうですか?
ケビン14年

確かに。この定式化は、データのふりをしたオブジェクトに相当します。そして、それらはデータですが、あまり有用なデータではありません。
ウォルターミッティ14年

この利点は、ほとんどの場合、アプリのv2をリリースするとすぐに消滅します。
アンディ14年

10

この種のデザインが理にかなっている場合があります。プロジェクトの目的と使用方法を説明せずに、これが適切かどうかを判断するのは困難です。

BLOBを保存するとDBAが嫌いになる場合がありますが、多くの場合、他の選択肢はテーブルをEntity-attribute-valueに変えることだけです。他の選択肢は、非リレーショナルデータベース、通常はオブジェクトベースまたは辞書ベースのデータベース、またはドキュメント指向データベースを使用することです。一部のDBA、特にリレーショナルのみを知っているDBAは、さらに情熱を持って嫌います。ただし、非リレーショナルデータベースには独自の問題がありますが、オブジェクトデータベースを使用してオブジェクトを保存すると、リレーショナルシステムで簡単に解決できる他の問題が明らかになる可能性があります。

私が考えていないことをこれを行うにはいくつかの利点がありますか?

シリアル化されたオブジェクトを保存するということは、スキーマレスデータを保存できることを意味します(名前にかかわらず、スキーマレスは通常、スキーマがまったくないことを意味するのではなく、暗黙的なスキーマのみがあることに注意してください)。開発時にスキーマを事前に定義できない可能性のある多くの問題ドメインがあり、従来のリレーショナルデータベースの設計に従うと、データベースのスキーマを1週間おきに変更する必要があるか、最終的にテーブルを持つことになります使用されていない列の80%、または実際に同じデータを格納する何百もの異なるテーブル。いずれも優れた設計を示していません。通常、この問題の原因は、リレーショナルデータベースに非リレーショナル問題ドメインを強制的にフィッティングしているためです。

もちろん、人々がEAV、スキーマレス、またはBLOBストアを使用する必要があると考えるプロジェクトはたくさんありますが、避けられない痛みを不必要に引き起こすことが判明しました。教授とは何であるかを明確に議論し、独自の議論を提供する必要があります。議論を聞いて、あなたが彼に同意するかもしれないし、そうでないかもしれない、彼が間違っているかもしれないという準備をしてください。


7

私は以前にこれをやったことがあります-しかし、特定のシナリオで有用な手法は、使用するシリアル化形式に依存します。これを行う場合は、モデルの古いバージョン(XMLなど)を逆シリアル化できるシリアル化形式を使用するようにします。

私は通常、データ形式が利点を提供しない複雑なリレーショナルモデルをもたらすシナリオでこれを使用します(たとえば、ビジネス要件がフィルタリングなどを必要としない場合...)、私はすでにデータベースを使用しています(その他のリレーショナルデータ)。そのようなケースの1つは、ユーザークエリを持つアプリケーションでした。リレーショナルモデルには、条件、ネストされた条件(OR / ANDなど)、並べ替えオプションなどを格納するための少数のテーブルがありました。データベースへの変更を必要とする新しい機能を追加する必要があったため、他のすべてのオプションを表すシリアル化されたblobを持つクエリの単一のテーブルですべてを置き換えました。

別のケースは、さまざまな「ジョブ」を処理するシステムでした。いくつかの異なるタイプのジョブがあり、各ジョブには異なるパラメーターがあり、それらのパラメーターに基づいてジョブを検索/フィルターできるビジネス要件はありません。これをリレーショナルデータベースとして保存するには、ジョブタイプごとに少なくとも1つの新しいテーブルが必要であり、新しいジョブタイプを追加することは困難です。代わりに、パラメーターはデータベースにblobとして保存されます。各ジョブタイプは、独自のパラメーターのシリアル化と逆シリアル化を行います。

このようなシナリオに出くわすことはあまりありませんが、上記のような状況が時々発生し、ブロブデータのシリアル化により作業の負荷が軽減され、アプリケーションのメンテナンス性が向上し、実質的な欠点はありません。


6

Justin Caveは、これが冗長データにつながる可能性があることは正しいですが、これは本当にデータベースの設計方法に依存します。

オブジェクト全体をblobにシリアル化するアプローチは、ここにいるほとんどの人が思っているほどとんでもないことではありません。実際、ここで説明したように、一部のアプリケーションでは、これがあなたができる最善の設計になる可能性があります:https : //stackoverflow.com/a/12644223/1121352

実際、オブジェクトをシリアル化すると、少なくとも2つの利点が得られます。

1- インピーダンスの不一致を減らす:特に多くのクラスとカスタム型を使用する場合、一部のJava型はSQLで使用できません。したがって、JavaオブジェクトからSQLへのやり取りは非常に面倒であり、あいまいさを招く可能性さえあります。

2- スキーマの柔軟性が向上。実際、リレーショナルスキーマは同じ構造を共有するデータには非常に優れていますが、単一のクラス内のオブジェクトの一部が実行時の条件に応じて異なるプロパティを持つことができる場合、リレーショナルスキーマはワークフローを大幅に妨げる可能性があります。

したがって、このアプローチには確かに利点があります(少なくともこれら2つ、しかし確かに私が引用しなかった他の2つ)が、当然、支払うべき莫大なコストは、ほとんどすべてのリレーショナルスキーマの利点を失うことです。

ただし、データベースを慎重に設計すると、両方の長所を最大限に活用できます。各オブジェクトに固有の属性を使用してリレーショナルスキーマ(つまり、一意のキー列)を設定し、そのオブジェクトをBLOBに格納できます。 。このようにして、オブジェクトの属性によって定義された一意の識別子を与えられたオブジェクトの高速な取得を保証し、冗長性を削減しますが、インピーダンスの不一致を解消し、Javaオブジェクトの完全な柔軟性を保ちます。

補足説明として、一部のDBメーカーは、PostSQLやPostgreSQLのJSONデータ型など、リレーショナルモデルとオブジェクトモデルを組み合わせて、JSONをリレーショナル列と同様に直接処理できるように、SQL3とOQL(オブジェクトSQLに(制限付き)オブジェクトサポートを追加するためのクエリ言語)。

結局、これはすべて設計の問題であり、リレーショナルモデルとオブジェクトモデルの間の妥協です。

コメントを読んだ後の/ EDIT:もちろん、データを検索可能(「クエリ可能」)にする必要がある場合は、データをblobとして保存しないでください。ただし、データの一部が検索可能ではなく、何らかのメタデータである場合、特にこのメタデータが柔軟な構造を持っている場合、このデータ部分をblob内のオブジェクトとして保存することは良い解決策になりますオブジェクトからオブジェクトに変更できます。


5

過去にこれを行ったときの実用的な例を挙げましょう。

マルチユーザーアプリケーションのすべてのデータを含むデータベースがあります。データベースには、アクセス権を持つユーザーのテーブルもあります。このデータはすべて、期待どおりに正規化されます。

次に、ユーザーが開いたウィンドウと実行していたことをアプリケーションに記憶させて、ユーザーが翌朝作業を開始したときに状態を復元できるようにする要求があります。

  • まず、これが時々失敗する場合、それは無礼ではありませんか

    • たとえば、誰かが初めてアプリケーションの新しいバージョンを使用する場合、開いていたウィンドウが忘れられるので、…
  • したがって、オブジェクトが変更されると100%のフォールバックが発生するため、ブロックを読み取ることができません。

  • アクセス制御、バックアップなどを備えた集中型データベースがすでにあります。
  • すべてのユーザーマシンがアクセスできる何らかのファイルサーバーにファイルを配置するか、これらのファイルを読み取るためにAPIを記述する必要があるため、データをファイルに保存するコストは高くなります。

別の時間には、長時間の計算を大量に行うアプリケーションがあり、ユーザーは、停電などがあった場合に最後に知っていた良い点から計算を再開できるようにしたいと考えていました。アプリケーションは計算を再開することが予想され、保存が必要なオブジェクトが多数あったため、データの正規化には費用がかかりました。

データベースがすでに配置され、明確に定義された正規化されたアプリケーションデータに使用されているため、それをブログの保存に使用しない本当の理由がないため、賢明で迅速なオプションを選択しました。


4

非常に重要な要因:Javaシリアル化(実装によって有効にされるものSerializable)は、それ自体非常に悪い形式であるため、実際に永続的なオブジェクトストレージに使用すべきではありません。

Javaシリアル化の欠点は次のとおりです。

  • データは他の言語からは実際には読み取りできません。
  • 直列化されたオブジェクトの上位互換性を維持することは非常に簡単ではありません。つまり、クラスにフィールドを追加(または削除)すると、以前のバージョンのクラスで作成されたオブジェクトを読むのはそれほど簡単ではありません。
  • それほど高速ではありません(ただし、走行距離は異なる場合があります)

したがって、他のシリアル化形式を使用する場合、素敵なKey-Valueストアを取得します。javaシリアル化を使用する場合は混乱します。


答えの事実は単純に偽です:1)形式は徹底的な仕様でカバーされています。2)フィールドの追加はまったく問題ありません。フォーマットは非常に柔軟です。3)速度は実際のデータに依存しますが、JSONやXMLなどの形式に匹敵します(場合によってはより速く、時にはより遅い)。基本的に、「データは他の言語からは実際には読めません」という1行を除いて、答え全体が間違っています。
fdreger 14年

1
1)間違っていたのは別として、答えの残りはIMOが有効です。あなたはdeserialisatonを制御したい場合は-あなたが追加したときに必要とされている/(finalフィールドを持つときには特に)、削除のフィールドは、インタフェースは不格好に見える、とあなたはそれがneccessaryであることをより多くのメソッドをオーバーライドする必要があるreadObjectreadReplace(finalフィールドのため)。
jb。

あなたは間違っています。フィールドの追加と削除にはメソッドを書く必要はありません。最終的なフィールドについては、元の回答ではまったく言及されておらず、言及されていても関係ありません(問題は他のすべての形式で共通です)。最後に、「それほど速くはありません(ただし、走行距離は異なる場合があります)」とは、単に何も意味しません。あなたにはただ一つの事実があります。それは他の言語に関するものです。これは、何かを「混乱」と呼ぶ非常に弱い基盤です。
fdreger

1
フィールドを追加するためにメソッドを記述する必要はありませんが、それらのデシリアライズ方法に影響を与えたい場合は、その動作を指定する必要があります。進化するオブジェクトスキーマの逆シリアル化に関する問題への参照を掘り下げてみます。
jb。

3

これは興味深いスレッドで、よく考えられた答えがいくつかあります。シリアル化されたオブジェクトの保存と取得のすべての意味に精通していないので、DBAチームまたは開発チームに答えを提供するのは興味深いと思います。

重要なのは、現在および将来の要件を満たし、将来のサポート作業を最小限に抑えるためにソリューションを可能な限りシンプルにすることです。機能要件と非機能要件(インフラストラクチャやデータベースなど)の両方を満たす必要があります。80/20ルールを覚えておいてください。ビジネスにとってのアプリの重要性と適切な開発努力を理解する。

データベーススペース、速度、およびメモリが問題にならない場合、それらにこだわらないでください。

DBMSが承認済みリストにある場合、コストが適切である限り、DBMSをソリューションで使用できます。リレーショナルデータベースを使用して単純なBLOBを保存しても、特に問題が単純化される場合は問題ありません。

解決策がプロトタイプまたは初期段階/バージョンである場合、物事をシンプルに保つことにさらに重点を置く必要があります。データスキーマは、計画する限りいつでも拡張できます。

リレーショナルデータベースは、スキーマが自己完結型のビジネスエリアをカバーし、ビジネスルールが厳格でない限り、整合性または一貫性を強制しません。(たとえば、直列化されたオブジェクトの質問に対するソリューションは、ルールを実施するために辞書/オントロジースタイルのリポジトリを考慮する場合があります)。

すべてのリレーショナルデータベースが純粋なリレーショナルデータベーススキーマ(スター、空間、非リレーショナルなど)を使用しないことを考慮すると、質問のように、アプリはリレーショナルデータベースを非リレーショナルストアとして使用することもできます。多くのコアビジネスデータベースはこのように機能します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.