29

このすばらしいNettuts+の記事のヒントを読んだ後、大量の読み取りが行われる他のテーブルから非常に揮発性の高いデータを分離し、同時にデータベーススキーマ全体で必要なテーブルの数を減らすテーブルスキーマを思いつきました。正規化のルールに従わないため、これが良いアイデアかどうかはわかりません。アドバイスを聞きたいのですが、一般的なアイデアは次のとおりです。


クラステーブル継承構造でモデル化された4種類のユーザーがあり、メインの「ユーザー」テーブルに、すべてのユーザーに共通のデータ(id、、、、いくつかusername、...)といくつかのフィールド( 、、、、、、)を格納します。 ..)。passwordflagsTIMESTAMPdate_createddate_updateddate_activateddate_lastLogin

上記のNettuts+の記事からヒント#16を引用するには:

例2:テーブルに「last_login」フィールドがあります。ユーザーがWebサイトにログインするたびに更新されます。ただし、テーブルを更新するたびに、そのテーブルのクエリキャッシュがフラッシュされます。そのフィールドを別のテーブルに配置して、ユーザーテーブルの更新を最小限に抑えることができます。

今ではさらにトリッキーになります。次のようなユーザー統計を追跡する必要があります。

  • ユーザープロファイルが表示された一意の回数
  • 特定のタイプのユーザー広告がクリックされたユニークな回数
  • 特定のタイプのユーザーからの投稿が表示されたユニークな回数
  • 等々...

私の完全に正規化されたデータベースでは、これにより約8〜10個の追加テーブルが追加されます。それほど多くはありませんが、できれば単純にしておきたいので、次の" events"テーブルを作成しました。

|------|----------------|----------------|---------------------|-----------|
| ID   | TABLE          | EVENT          | DATE                | IP        | 
|------|----------------|----------------|---------------------|-----------|
| 1    | user           | login          | 2010-04-19 00:30:00 | 127.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
| 1    | user           | login          | 2010-04-19 02:30:00 | 127.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
| 2    | user           | created        | 2010-04-19 00:31:00 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 2    | user           | activated      | 2010-04-19 02:34:00 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 2    | user           | approved       | 2010-04-19 09:30:00 | 217.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
| 2    | user           | login          | 2010-04-19 12:00:00 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15   | user_ads       | created        | 2010-04-19 12:30:00 | 127.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
| 15   | user_ads       | impressed      | 2010-04-19 12:31:00 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15   | user_ads       | clicked        | 2010-04-19 12:31:01 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15   | user_ads       | clicked        | 2010-04-19 12:31:02 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15   | user_ads       | clicked        | 2010-04-19 12:31:03 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15   | user_ads       | clicked        | 2010-04-19 12:31:04 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15   | user_ads       | clicked        | 2010-04-19 12:31:05 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 2    | user           | blocked        | 2010-04-20 03:19:00 | 217.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
| 2    | user           | deleted        | 2010-04-20 03:20:00 | 217.0.0.1 |
|------|----------------|----------------|---------------------|-----------|

基本的に、はテーブルIDの主キー(id)フィールドを指しTABLEますが、残りはかなり簡単なはずです。この設計で私が気に入った点の1つは、最後のログインだけでなく、すべてのユーザーログインを追跡できるため、そのデータを使用していくつかの興味深いメトリックを生成できることです。

テーブルの性質が大きくなっているためevents、次のようないくつかの最適化を行うことも考えました。

  • #9:有限数のテーブルと有限(および所定の)数のイベントしかないため、スペースを節約するために、TABLEおよび列をsではなくsEVENTSとして設定できます。ENUMVARCHAR
  • #14IPsをUNSIGNED INTsの代わりINET_ATON()にsとして保存しVARCHARます。
  • sDATETIMESTAMPsではなくsとして保存しDATETIMEます。
  • /の代わりにARCHIVEまたはCSV)エンジンを使用します。 InnoDBMyISAM
    • INSERTsとsのみSELECTがサポートされており、データはその場で圧縮されます。

全体として、各イベントは14(非圧縮)バイトしか消費しません。これは私のトラフィックには問題ないと思います。

長所:

  • より詳細なデータ(ログインなど)を保存する機能。
  • ほぼ12個の追加のテーブル(日付と統計)を設計(およびコーディング)する必要はありません。
  • テーブルごとに数列を削減し、揮発性データを分離します。

短所:

  • 非リレーショナル(まだEAVほど悪くはない):
    • SELECT * FROM events WHERE id = 2 AND table = 'user' ORDER BY date DESC();
  • イベントごとに6バイトのオーバーヘッド(、、IDおよびTABLEEVENT

長所が短所をはるかに上回っているように見えるので、私はこのアプローチを採用する傾向がありますが、それでも私は少し気が進まない...何かが足りないのですか?これについてどう思いますか?

ありがとう!


@coolgeek:

私が少し違うことの1つは、entity_typeテーブルを維持し、そのIDをobject_type列(この場合は「TABLE」列)で使用することです。event_typeテーブルでも同じことをしたいと思うでしょう。

明確にするために、テーブルで許可されるイベントをマップするテーブルを追加し、TABLE/EVENTペアを使用する代わりにイベントテーブルでそのテーブルのPKを使用する必要があることを意味しますか?


@ben:

これらはすべて既存のデータから得られた統計ですよね?

追加のテーブルは主に統計に関連していますが、データはまだ存在していません。いくつかの例を示します。

user_ad_stats                          user_post_stats
-------------                          ---------------
user_ad_id (FK)                        user_post_id (FK)
ip                                     ip
date                                   date
type (impressed, clicked)

これらのテーブルを削除すると、誰が、何を、いつ、ビューがここでどのように役立つかを追跡する方法がありません。

私はそれが分離されるべきであることに同意しますが、それは根本的に異なるデータであるためです。誰かが何であるか、そして誰かが何をするかは、2つの異なることです。ボラティリティはそれほど重要ではないと思います。

私はそれを両方の方法で聞いたが、MySQLのマニュアルにはどちらかが正しいと述べているものは何も見つからなかった。とにかく、それらはデータの種類を表すため、別々のテーブルにする必要があることに同意します(通常のアプローチよりも説明的であるという追加の利点があります)。

いわば、木々の森が欠けていると思います。

テーブルの述語は「DATEEVENTEDTOTABLEの時点でのIPIPからのユーザーID」であり、妥当と思われますが、問題があります。

「EAVほど悪くない」という意味は、すべてのレコードが線形構造に従っていて、クエリが非常に簡単であるということです。階層構造がないため、すべてのクエリを単純なで実行できますSELECT

あなたの2番目の声明に関して、あなたは私をここで間違って理解したと思います。IPアドレスは必ずしもユーザーに関連付けられているとは限りません。テーブル構造は次のようになります。

IPアドレス( )は、日付()にテーブル( )のPK()に対してIP何か( )を実行しました。EVENTIDTABLEDATE

たとえば、上記の例の最後の行では、IP 217.0.0.1(一部の管理者)が2010-04-20 03:20:00にユーザー#2(最後の既知のIPは127.0.0.2)を削除したことを示しています。 。

たとえば、ユーザーイベントをユーザーに参加させることはできますが、外部キー制約を実装することはできません。

確かに、それが私の主な関心事です。ただし、従来のリレーショナルデザインではうまくいかなかったこのデザインで、何がうまくいかないのか完全にはわかりません。いくつかの注意点を見つけることができますが、データベースをいじっているアプリがそれが何をしているのかを知っている限り、問題はないはずです。

この議論で重要なもう1つのことは、私がはるかに多くのイベントを保存することです。各イベントは元の設計と比較して2倍以上になります。ここでストレージエンジンを使用することは完全に理にかなっていますがARCHIVE、唯一のことはそうではないということです。 sをサポートしますFKUPDATEsでもDELETEsでもありません)。

4

3 に答える 3

5

このアプローチを強くお勧めします。おそらくOLTPとOLAPに同じデータベースを使用しているため、いくつかの星と雪片を追加することで、パフォーマンスを大幅に向上させることができます。

私は現在65のテーブルにあるソーシャルネットワーキングアプリを持っています。オブジェクト(ブログ/投稿、フォーラム/スレッド、ギャラリー/アルバム/画像など)のビューを追跡するための単一のテーブル、オブジェクトの推奨のための別のテーブル、および他の12のテーブルの挿入/更新アクティビティを要約するための3番目のテーブルを維持します。

私が少し違うことの1つは、entity_typeテーブルを維持し、そのIDをobject_type列(この場合は「TABLE」列)で使用することです。event_typeテーブルでも同じことをしたいと思うでしょう。

Alixの明確化-はい、オブジェクトの参照テーブルとイベントの参照テーブルを維持します(これらはディメンションテーブルになります)。ファクトテーブルには次のフィールドがあります。

id
object_id
event_id
event_time
ip_address
于 2010-04-20T05:56:45.977 に答える
3

それはかなり合理的なデザインのように見えるので、私はあなたがしていることの具体的な理由があることを確認するためにあなたの仮定のいくつかに挑戦したかっただけです。

私の完全に正規化されたデータベースでは、これにより最大で約8〜10個のテーブルが追加されます

これらはすべて既存のデータから得られた統計ですよね?(更新:わかりました、そうではないので、以下を無視してください。)なぜこれらは単にビュー、またはマテリアライズドビューではないのですか?

ただし、これらの統計を収集するのは遅い操作のように見えるかもしれません。

  • 適切なインデックス作成により、非常に高速になります
  • 一般的な操作ではないので、速度はそれほど重要ではありません
  • 冗長データを排除すると、他の一般的な操作が高速で信頼できるものになる可能性があります

非常に揮発性の高いデータを、大量の読み取りが行われる他のテーブルから分離するテーブルスキーマを考え出しました。

かなり不安定なユーザー(1つのテーブルを選択するだけ)のイベントがユーザーデータからどのように分離されるかについて話していると思います。私はそれが分離されるべきであることに同意しますが、それは根本的に異なるデータであるためです。誰かが何であるか、そして誰かが何をするかは、2つの異なることです。

ボラティリティはそれほど重要ではないと思います。DBMSでは、ログファイルとデータベースファイルを別々のデバイスに配置できるようになっているはずです。これにより、同じことが実現されます。行レベルのロックでは、競合が問題になることはありません。

非リレーショナル(まだEAVほど悪くはない)

いわば、木々の森が欠けていると思います。

テーブルの述語は「DATEEVENTEDTOTABLEの時点でのIPIPからのユーザーID」であり、妥当と思われますが、問題があります。(更新:わかりました、それはちょっとそのようなものです。)

たとえば、ユーザーイベントをユーザーに参加させることはできますが、外部キー制約を実装することはできません。そのため、 EAVは一般的に問題があります。何かが正確にEAVであるかどうかは実際には重要ではありません。スキーマに制約を実装するのは通常1行または2行のコードですが、アプリでは数十行のコードになる可能性があり、複数のアプリが同じデータに複数の場所でアクセスすると、簡単に数千行に増える可能性があります。コード行。したがって、一般に、外部キー制約を使用して不正なデータを防ぐことができれば、アプリがそれを行わないことが保証されます。

イベントはそれほど重要ではないと思うかもしれませんが、例として、広告の表示回数はお金です。デザインプロセスのできるだけ早い段階で、広告の表示に関連するバグを見つけたいと思います。

さらなるコメント

いくつかの注意点を見つけることができますが、データベースをいじっているアプリがそれが何をしているのかを知っている限り、問題はないはずです。

そして、いくつかの注意点があれば、非常に成功したシステムを作ることができます。適切な制約システムを使用すると、「データベースをいじっているアプリが何をしているのかわからない場合、DBMSはエラーにフラグを立てます」と言うことができます。それはあなたが持っているよりも多くの時間とお金を必要とするかもしれません、それであなたが持つことができるより単純なものはあなたができないより完璧なものよりおそらく良いでしょう。C'estlavie。

于 2010-04-20T08:17:38.103 に答える
0

ベンの答えにコメントを追加できないので、2つのこと...

まず、スタンドアロンのOLAP/DSSデータベースでビューを使用することは1つのことです。トランザクションデータベースでそれらを使用することはまったく別のことです。高性能MySQLの人々は、パフォーマンスが重要な場所でビューを使用しないことを推奨しています

WRTデータの整合性に同意します。これは、「イベント」を中央のファクトテーブルとして使用するスターまたはスノーフレークを使用することのもう1つの利点です(また、私のように複数のイベントテーブルを使用することもできます)。ただし、IPアドレスに関する参照整合性スキームを設計することはできません

于 2010-04-20T13:42:00.107 に答える