249

バックグラウンド

私は CS の 1 年生で、父の中小企業でアルバイトをしています。実際のアプリケーション開発の経験はありません。私は Python でスクリプトを書き、C でいくつかのコースワークを作成しましたが、このようなものはありません。

私の父は小規模なトレーニング ビジネスを経営しており、現在、すべてのクラスは外部の Web アプリケーションを介してスケジュール、録画、フォローアップされています。エクスポート/「レポート」機能がありますが、非常に一般的であり、特定のレポートが必要です。クエリを実行するために実際のデータベースにアクセスすることはできません。カスタム レポート システムのセットアップを依頼されました。

私の考えは、一般的な CSV エクスポートを作成し、(おそらく Python を使用して) オフィスで毎晩ホストされている MySQL データベースにインポートし、そこから必要な特定のクエリを実行することです。データベースの経験はありませんが、基本的なことは理解しています。データベースの作成と正規形について少し読んだことがあります。

すぐに国際的な顧客を獲得し始めるかもしれないので、それが起こった場合にデータベースが爆発しないようにしたい. また、現在、いくつかの大企業を顧客としており、さまざまな部門があります (例: ACME 親会社、ACME ヘルスケア部門、ACME ボディケア部門)。

私が思いついたスキーマは次のとおりです。

  1. クライアントの観点から:
    • クライアントがメインテーブル
    • クライアントは、所属する部門にリンクされています
      • 部門は、ロンドンの人事部、スウォンジーのマーケティングなど、国中に分散している可能性があります。
      • 部門は会社の部門にリンクされています
    • 部門は親会社にリンクされています
  2. クラスの観点から:
    • セッションはメインテーブルです
      • 教師は各セッションにリンクされています
      • 各セッションには statusid が与えられます。例: 0 - 完了、1 - キャンセル
      • セッションは、任意のサイズの「パック」にグループ化されます
    • 各パックはクライアントに割り当てられます

私はスキーマを 1 枚の紙に "設計" (走り書きのようなもの) し、3 番目の形式に正規化したままにしようとしました。次に、MySQL Workbench にプラグインすると、すべてきれいになりました:
(フルサイズのグラフィックはここをクリック)

代替テキスト
(ソース: maian.org )

実行するクエリの例

  • クレジットがまだ残っているクライアントのうち、非アクティブなクライアント (今後クラスが予定されていないクライアント)
  • クライアント/部門/部門ごとの出席率は? (各セッションのステータス ID で測定)
  • 教師は月に何回授業を受けましたか
  • 出席率の低いクライアントにフラグを立てる
  • 部門内の人々の出席率を含む人事部門のカスタム レポート

質問

  • これはオーバーエンジニアリングですか、それとも正しい方向に向かっていますか?
  • ほとんどのクエリで複数のテーブルを結合する必要があると、パフォーマンスが大幅に低下しますか?
  • おそらく一般的なクエリになるため、「lastsession」列をクライアントに追加しました。これは良い考えですか、それともデータベースを厳密に正規化する必要がありますか?

御時間ありがとうございます

4

11 に答える 11

43

あなたの質問に対するいくつかの回答:

1) このような問題に初めて取り組む人にとって、あなたはほぼ的を射ています。この質問に関する他の人からの指摘は、これまでのところほとんどカバーしていると思います。よくできた!

2 & 3) パフォーマンスへの影響は、特定のクエリ/手順、さらに重要なことに、レコードの量に対して適切なインデックスを使用して最適化することに大きく依存します。メイン テーブルの 100 万をはるかに超えるレコードについて話している場合を除き、合理的なハードウェアではパフォーマンスが問題にならない十分に主流の設計を採用する方向に向かっているようです。

そうは言っても、これはあなたの質問3に関連しています。最初は、ここでの正規化の正統性に対するパフォーマンスや過敏性について過度に心配する必要はないでしょう。これは構築中のレポート サーバーであり、トランザクション ベースのアプリケーション バックエンドではなく、パフォーマンスや正規化の重要性に関してプロファイルが大きく異なります。ライブ サインアップおよびスケジューリング アプリケーションをサポートするデータベースは、データを返すのに数秒かかるクエリに注意する必要があります。レポート サーバー機能は、複雑で長いクエリに対する許容度が高いだけでなく、パフォーマンスを向上させるための戦略も大きく異なります。

たとえば、トランザクション ベースのアプリケーション環境では、ストアド プロシージャとテーブル構造を n 次までリファクタリングすることや、頻繁に要求される少量のデータ用のキャッシュ戦略を開発することが、パフォーマンス向上のオプションに含まれる場合があります。レポート環境では確かにこれを行うことができますが、スケジュールされたプロセスが実行され、事前構成されたレポートが保存され、ユーザーがデータベース層にストレスをかけずにスナップショット データにアクセスするスナップショット メカニズムを導入することで、パフォーマンスにさらに大きな影響を与えることができます。リクエストベース。

これはすべて、作成しているデータベースの役割を考えると、採用する設計原則とトリックが異なる可能性があることを説明するための、長々とした暴言です。お役に立てば幸いです。

于 2010-02-23T19:44:49.247 に答える
14

あなたは正しい考えを持っています。ただし、それをクリーンアップして、マッピング (has*) テーブルの一部を削除することはできます。

できることは、Departments テーブルに CityId と DivisionId を追加することです。

それ以外は、すべて問題ないと思います...

于 2010-02-23T18:28:30.870 に答える
6

私が行う唯一の変更は次のとおり
です。

2-可能であれば、int idをGUID(uniqueidentifier)に変更します(これは私の個人的な好みかもしれません)。最終的に複数の環境 (dev/test/staging/prod) を持つようになったと仮定すると、ある環境から別の環境にデータを移行することが必要になる場合があります。GUID ID を使用すると、これが大幅に簡単になります。

3- 会社 -> 部門 -> 部門構造の 3 つのレイヤーでは不十分な場合があります。さて、これはオーバーエンジニアリングかもしれませんが、n レベルの深さをサポートできるようにその階層を一般化することができます。これにより、一部のクエリがより複雑になるため、トレードオフの価値がない場合があります。さらに、より多くのレイヤーを持つクライアントは、このモデルに簡単に「詰め込む」ことができます。

4- VARCHAR であり、Statuses テーブルへのリンクがないクライアント テーブルにもステータスがあります。クライアントステータスが何を表しているかについて、もう少し明確になると思います。

于 2010-02-23T18:45:55.377 に答える
6

いいえ。かなり詳細なレベルで設計しているようです。

国と企業は、都市と部門と同様に、あなたの設計では実際には同じエンティティだと思います。国と都市のテーブル (および Cities_Has_Departments) を削除し、必要に応じてブール値フラグ IsPublicSector を Companies テーブルに追加します (または、単なる民間部門/公共部門以外の選択肢がある場合は CompanyType 列)。

また、Departments テーブルの使い方に誤りがあると思います。Departments テーブルは、各顧客部門が持つことができるさまざまな種類の部門への参照として機能しているようです。その場合は、DepartmentTypes という名前にする必要があります。しかし、あなたのクライアント (出席者だと思います) は、部門 TYPE に属しておらず、会社の実際の部門インスタンスに属しています。現状では、特定のクライアントがどこかの人事部門に属していることはわかりますが、どの部門かはわかりません!

つまり、クライアントは、Divisions_Has_Departments と呼ばれるテーブルにリンクされている必要があります (ただし、単に Departments と呼びます)。その場合、データベースで標準の参照整合性を使用する場合は、上記のように都市を分割して分割する必要があります。

于 2010-02-23T20:21:54.460 に答える
5

ところで、既に CSV を生成していて、それらを mySQL データベースにロードしたい場合は、LOAD DATA LOCAL INFILE が最適です: http://dev.mysql.com/doc/refman/5.1/ en/load-data.html . Mysqlimport も検討する価値があり、基本的にロード データ インファイルの優れたラッパーであるコマンド ライン ツールです。

于 2010-03-01T19:59:52.040 に答える
3

ほとんどのことはすでに言われていますが、私は1つ追加できると思います。若い開発者がパフォーマンスについて少し前もって心配することは非常に一般的であり、テーブルの結合に関するあなたの質問はその方向に向かっているようです。これは、「早期最適化」と呼ばれるソフトウェア開発のアンチパターンです。あなたの心からその反射を追放してみてください:)

もう1つ、「都市」と「国」のテーブルが本当に必要だと思いますか?ユースケースには、departmentsテーブルに「city」列と「country」列を含めるだけで十分ではないでしょうか。たとえば、アプリケーションで都市ごとに部門をリストし、国ごとに都市をリストする必要がありますか?

于 2010-02-23T20:03:13.127 に答える
3

以下は、ビジネス インテリジェンス/レポート スペシャリストおよび戦略/計画マネージャーとしての役割に基づいたコメントです。

  1. 上記のラリーの指示に同意します。私見、それはそれほど設計されすぎているわけではありません。いくつかのものは少し場違いに見えます. 簡単にするために、クライアントに会社 ID、部門の説明、部門の説明、部門タイプ ID、部門タイプ ID を直接タグ付けします。部門タイプ ID と部門タイプ ID を、ルックアップ テーブルと内部レポート/分析フィールドへの参照として使用して、長期的な一貫性を確保します。

  2. パック テーブルには「クレジット」列が含まれていますが、実際にはクライアント ベース テーブルに結び付けられるべきではありません。したがって、パックが多数ある場合、将来のクラスにどれだけのクレジットが残っているかを確認できますか? アプリケーションは計算を処理し、クライアント テーブルに一元的に格納できます。

  3. 会社情報は、明らかな住所/電話/などを含む、さらに多くのフィールドを使用できます。情報。また、D&B の「DUN」列 (サイト/ブランチ/究極) を長期的に追加する準備ができています。Dun and Bradstreet (D&B) には膨大な企業カタログがあり、後でそれらの情報が非常に役立つことがわかります。レポート/分析用。これにより、言及した複数の部門の問題が処理され、サブ/部門/ブランチ/などの階層をロールアップできるようになります。大軍団の。

  4. 作業するレコードの数については言及していません。これは、事前にパッケージ化された「レポート」ソフトウェアを使用して、より迅速かつはるかに少ない頭痛の種で実行できた可能性のある大規模な開発イニシアチブに備えることを意味する可能性があることを意味します. 大規模なデータベース (< 65000 行) を扱っていない場合は、MS-Access、OpenOffice (ベース)、または関連するレポート/アプリ開発ソリューションがそのトリックを実行できないことを確認してください。私は自分で Oracle の無料の APEX ソフトウェアをかなり使用しています。無料のデータベース Oracle XE が付属しており、サイトからダウンロードするだけです。

  5. 参考までに - レポートの洞察: 大規模なデータベースの場合、通常、2 つのデータベース インスタンスがあります。a) 各詳細レコードを記録するためのトランザクション データベース。b) 別のマシンに格納されたレポート データベース (データ マート/データ ウェアハウス)。詳細については、Google で Star Schema と Snowflake Schema の両方を検索してください。

よろしく。

于 2010-02-23T21:53:29.097 に答える
2

複数のテーブルに結合するとパフォーマンスが低下するという懸念のみに対処したいと思います。結合を行う必要があるため、正規化を恐れないでください。結合はリレーショナル データベースでは通常のことであり、予期されるものであり、適切に処理できるように設計されています。PK/FK 関係を設定する必要があります (データの整合性のために、これは設計時に考慮することが重要です) が、多くのデータベースでは FK は自動的にインデックス化されません。これらは結合で使用されるため、FKS のインデックス作成から開始することをお勧めします。PK は通常、一意である必要があるため、作成時にインデックスを取得します。データ ウェアハウスの設計によって結合の数が減るのは事実ですが、通常、1 つのレポートで何百万ものレコードにアクセスする必要があるまで、データ ウェアハウスのポイントには到達しません。それでも、ほとんどすべてのデータ ウェアハウスは、リアルタイムでデータを収集するためのトランザクション データベースから開始し、その後、データはスケジュールに従って (毎晩、毎月、またはビジネス ニーズに応じて) ウェアハウスに移動されます。したがって、レポートのパフォーマンスを向上させるために後でデータ ウェアハウスを設計する必要がある場合でも、これは良い出発点です。

あなたのデザインは、CS の 1 年生にとって印象的だと言わざるを得ません。

于 2010-02-24T16:33:27.737 に答える
1

私はトレーニング/学校の分野で働いてきましたが、一般的に「セッション」(特定のコースのインスタンス) とコース自体の間には M:1 の関係があることを指摘したいと思います。つまり、あなたのカタログはコース (「スペイン語 101」など) を提供していますが、1 学期中に 2 つの異なるインスタンス (スミスが教える火~木、ジョーンズが教える水~金) がある可能性があります。

それ以外は、良いスタートのようです。クライアント ドメイン (「クライアント」につながるグラフ) は、モデル化したよりも複雑であることがわかると思いますが、ガイドとなる実際のデータが得られるまで、それをやりすぎないでください。

于 2010-02-23T18:40:24.343 に答える
1

過度に設計されているわけではありません。これが私が問題に取り組む方法です。結合は問題ありません。パフォーマンスが大幅に低下することはありません (推奨されていないデータベースを非正規化しない限り、完全に必要です!)。ステータスについては、代わりに enum データ型を使用してそのテーブルを最適化できるかどうかを確認してください。

于 2010-02-23T18:21:04.710 に答える
0

いくつかのことが頭に浮かびました:

  1. テーブルはレポート作成用に見えましたが、実際にビジネスを運営するためのものではありませんでした。クライアントがサインアップすると、基本的にクライアントがセッションのリストに参加するための注文が行われ、その注文は 1 つの会社の複数の従業員に向けられると思います。「注文」テーブルが実際にシステムの中心にあり、データのキャプチャと最終的なレポートを推進しているように思えます。(ビジネスを運営するために使用してきた紙の文書とデータベースの設計を比較して、論理的な一致があるかどうかを確認してください。)

  2. 多くの場合、企業には部門がありません。従業員は、場合によってはセッションの途中で部門/部門を変更することもあります。企業は部門/部門を追加/削除/改名することがあります。テーブルのコンテンツがリアルタイムで変化する可能性があるために、その後のレポート作成やグループ化が困難にならないようにしてください。非常に多くの連絡先データが非常に多くのテーブルに分割されているため、レポートを意味のある包括的なものにするために、非常に厳密なデータ入力検証を実施する必要がある場合があります。たとえば、新しいクライアントが追加されたとき、彼の会社/部門/部門/都市が同僚と同じ値であることを確認します。

  3. 「パック」の概念はまったく明確ではありません。

  4. 中小企業とのことなので、現在のマシンの速度と容量を考えると、パフォーマンスが問題になるとは驚きです。

于 2010-06-28T00:02:09.523 に答える