0

配列をmysqlに格納することに関して、ここや他の場所で多くの強力なステートメントを読みました。正規化のルールは、その悪い考えを示唆しているようであり、格納された配列内を検索すると、エレガントでないコードが助長されます。ただし、私が取り組んでいるアプリケーションの場合、フィールドに配列を格納することは合理的な解決策のようです。それは誰もがこの立場で間違って考えていることだと確信していますが、私はより良い方法を理解することはできません。設定は次のとおりです。

登録済みの学生、受講できるコース、および各コースでのパフォーマンスを保存する一連のテーブルがあります。重複やエラーを避けるために、すべてが「正規化」されています。「myCourses」セクションを生成できるようにしたいので、ログイン後、学生は資格のあるコースと受講したコースを確認できますが、自由に確認できます。頭に浮かぶアプローチは2つの配列です。my_eligible_coursesおよびmy_completed_courses。登録時に、学生には資格のある一連のコースが与えられます。これは、受講できるコースごとに1つずつ、studentidが複数出現する行として保存できます。

学生1コース1学生1コース2学生1コースn

次に、テーブルは、学生1の対象となるすべてのコースについて照会され、学生がログインしたときにリストとして表示されます。

または、studentidを主キーにし、「eligible_courses」列に配列(コース1、コース2、コースn)を含めることもできます。

受講したすべてのコースと生徒の成績に関連する指標を記録するための、生徒の成績の表があります。生徒の成績やコースの質などについて報告するように求められますが、この表はかなり大きくなります。my_completed_coursesのリストを生成する最も効率的な方法は、ログインするたびに学生IDでこのテーブルをクエリして、完了したコースのリストを提供することだとは信じられません。

もう1つの厄介な問題は、学生が適格なコースのセットは可変であり、新しいコースが開発されるにつれて拡大することです。これは、新しいコースごとに新しい列のセットを生成することは悪い考えであることを示唆しているようです。たとえば、newcourse_name 、pretest_score、posttest_score、time_to_complete、...また、新しい各コースのテーブルは、単純なリストのセットを生成するという比較的ありふれたエンドポイントの複雑なソリューションのように見えます。

それで、質問を言い換えると、登録された学生テーブルに適格で完了したコースの「不法な」配列リストを保存するか、これらのリストを動的に生成する方が良いでしょうか?

これはまだあいまいすぎると思いますが、エレガントでない配列と再構築されたスキーマの例を示すデータベース設計についての議論をいただければ幸いです。

4

3 に答える 3

1

これは、次の 2 つの明らかな理由から悪い考えです。

  1. DBMS は適切な参照X (および場合によってはドメイン) の整合性を強制することはできず、アプリケーション レベルの整合性に依存することは、ほとんど常に悪い考えです。
  2. データベースは「特定の学生に基づいて、コースを教えてください」というクエリに答えることができますが、必要に応じて反対方向に (効率的に) 進むことはできません。

Xバグのあるアプリケーションが存在しない ID を配列に格納するのを止めるには? または、学生がまだ参照しているコースを削除しますか? アプリケーションがコースの削除に注意を払っていても、それを効率的に行う方法はありません。すべての配列を調べるには、テーブル全体をスキャンする必要があります。

なぜこれを試しているのですか?リンク (別名、ジャンクション) テーブルは、これらの問題を解決します。

ストレージ容量が本当に心配な場合は、DBMS を切り替えて、最先端のインデックス圧縮をサポートするもの ( Oracleなど) を使用することもできます。

my_completed_courses のリストを生成する最も効率的な方法は、ログインするたびに学生 ID でこのテーブルをクエリして、完了したコースのリストを提供することであるとは信じがたいです。

データベースは、膨大な量のデータを照会するのに非常に優れています。この場合、クラスタリングを適切に使用すると、DBMS は非常に少ない I/O 操作でこのデータを取得できるため、非常に高速になります。実際のベンチマークを実行しましたか? 実際のパフォーマンスの問題を測定しましたか?

また、新しいコースごとのテーブルは、単純なリストのセットを生成するという比較的平凡なエンドポイントに対する複雑なソリューションのように思えます。

新しいテーブルを生成することは、異なる列を持つ場合に正当化される場合があります。しかし、それはあなたがやろうとしていることのようには聞こえません。


あなたが単に必要とするのは私には思えます:

ここに画像の説明を入力

CHECK (
    (COMPLETED = 0 AND (performance fields) IS NULL)
    OR (COMPLETED = 1 AND (performance fields) IS NOT NULL)
)
  • 学生がコースに登録したら、STUDENT_COURSE に行を挿入し、COMPLETED を 0 に設定し、パフォーマンス フィールドを NULL のままにします。
  • 学生がコースを修了したら、COMPLETED を 1 に設定し、パフォーマンス フィールドに入力します。

(ところで、COMPLETED を完全に省略して、NULL のパフォーマンス フィールドをテストするだけに頼ることもできます。)

InnoDB テーブルはクラスター化されています。これは、同じ学生に属する STUDENT_COURSE の行が物理的に近くに格納されていることを意味します。つまり、特定の学生のコースを取得するのが非常に高速であることを意味します。

逆方向に進む必要がある場合 (特定のコースの学生を取得する)、同じフィールドに逆の順序でインデックスを追加します: {COURSE_ID, STUDENT_ID}。この場合、カバーすることを検討することもできます。

少数の行について話しているので、 COMPLETED をインデックスなしのままにしておくことは問題ありません。それについて本当に心配している場合は、次のようなこともできます。

ここに画像の説明を入力

COMPLETED_STUDENT_COURSE は、完了したコースのみの B ツリーです (基本的に、すべての登録済みコースの B ツリーである STUDENT_COURSE のサブセットです)。

于 2012-07-05T10:42:35.293 に答える
1

my_completed_courses適切な列のテーブルにインデックスがある場合、クエリは非常に迅速になると確信する必要があります。

テーブルが大きくなり、速度が低下したと感じる場合は、MySQL サーバーを適切なメモリ割り当て設定で構成して、より多くのデータをメモリにキャッシュしておくことができます。または、今それを調べることもできます。

新しいコースの追加について行った編集への対応: 各コースに新しい列を追加しないでください。コースごとに新しいテーブルを追加しないでください。コースのテーブルを作成し、コースごとに行を追加します。

その後、インデックス付きの列でテーブルを結合して、必要なデータのリストを生成できるはずです。

于 2012-07-05T02:32:13.537 に答える
0

良い決断を下すのに役立つと思われるいくつかの考えを次に示します。

  1. 一般に、正しく正規化されたテーブルを使用することがルールです。しかし、これに例外があります。おそらくあなたのプロジェクトはそのようなものかもしれません

  2. ほとんどの場合、新しい開発者はデータを DB に入れることに集中する傾向があります。特定の目的のためにそれを取得することになると、彼らは立ち往生します。したがって、配列とリレーショナル テーブルの両方のケースを考慮して、どちらの方法が目的にかなうかを自問してください。たとえば、学生 X のコースを一覧表示する場合は、配列メソッドで問題ありません。学生証のように主キーで取得できるからです。しかし、コース A に何人の学生がいるか知りたい場合、配列メソッドは恐ろしい方法です。

  3. 繰り返しますが、上記の点はデータ量にも依存します. たとえば、約 100 人の学生しかいない場合、パフォーマンスの違いに気付かない可能性があります。しかし、数千のレコードを調べていて、学生向けのコースのリストが膨大な場合、配列アプローチは適していません

  4. 基準。これは、答えを見つけるための最良の方法です。MySQL の Explain を使用するか、クエリを実行するプログラムを使用して時間を計ることができます。標準的なデータ量で各方法を試して、どれが最適かを確認してください。たとえば、最近、MySQL は ISAM エンジンの強さを自慢していました。その後、何百万ものレコードを含む大規模なアプリケーションに取り組まなければなりませんでした。ここで、新しいレコードが入るたびに、インデックスを再構築する必要があることに気付きました。だから今、私たちはルールを曲げなければなりませんでした。同様に、正しい量のデータを使用してテストを行い、より適切な決定を下したほうがよいでしょう。

ただし、この例を原則として採用しないでください。むしろ、正規化の基準に従い、例外のルールのみを曲げてください。

于 2012-07-05T02:55:43.043 に答える