1

MYSQL/PHP で、人々がサイトで行った活動の記録を作成したいと考えています。

Table ADDED -> EventID, UserID, Time, IP

Table DELETED -> EventID, UserID, Time, IP

Table SHARED -> EventID, UserID, Time, IP.

たとえば、 によって実行された最後の 10 個のアクションを読み取るためにクエリを実行するときに、これらのテーブルを結合する方が効率的ですUSERIDか、それともこのように構造化する方が効率的でしょうか。

Table EVERYTHING -> EventID, EventType(eg ADDED, DELETED, SHARED), UserID, Time, IP 
4

2 に答える 2

3

2 番目の提案のように、すべてのイベントをログに記録し、イベントの種類を区別する 1 つのテーブルを使用します。

ここでは 1 種類のデータのみを格納しているため、1 つのテーブルに格納するのが適切です。初期段階では、時間の経過とともにテーブルが大きくなるサイズについてあまり心配する必要はありません。このようなテーブルには数列しかないため、パーティション分割を検討する前に、何百万行にも簡単に成長する可能性があります。

イベントの種類の数が限られている場合は、列にデータ型を使用することを検討してください。ENUM()EventType

于 2012-05-18T01:52:40.673 に答える
1

適切に正規化されているため、1 つのテーブルを使用するのが適切です。新しいイベント タイプを追加しても、新しいテーブルは必要ありません。また、参照整合性を維持し、インデックスを使用してユーザーのすべてのイベントを取得およびソートすることも、はるかに簡単です。(それらが別々のテーブルにある場合、ユーザーのすべてのイベントを取得して時間順に並べ替えると、1 つのテーブルを使用するよりもはるかに遅くなる可能性があります!)

ただし、スペースを節約し、インデックスを小さく保つために、これらのテーブルを小さくする方法があります。

  • を使用しenum()て、イベント タイプを定義します。イベントの数が少ない場合は、行ごとに最大 1 バイトを使用します。
  • UNSIGNED整数型を使用して、同じバイト数からより多くの sEventIDを取得します。UserID
  • 日付の全範囲が必要ない場合 (おそらく)、TIMESTAMP 型を使用して、DATETIME 型と比較して行あたり 4 バイトを節約します。
  • ipv4 アドレスのみを使用している場合は、IP を符号なしの 4 バイト整数として保存し、INET_ATON() と INET_NTOA() を使用して相互に変換します。これが最大の勝者です。VARCHAR 型は少なくとも 16 バイト必要であり、固定行長形式を使用できる可能性があります。

次のような表形式をお勧めします。

CREATE TABLE Events (
    `EventID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    `UserID` MEDIUMINT UNSIGNED NOT NULL COMMENT 'this allows a bit more than 16 million users, and your indexes will be smaller',
    `EventType` ENUM('add','delete','share') NOT NULL,
    `Time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `IP` INTEGER UNSIGNED NOT NULL DEFAULT 0,
    PRIMARY KEY (`EventID`),
    FOREIGN KEY (`UserID`) REFERENCES `Users` (`UserId`) ON UPDATE CASCADE ON DELETE CASCADE,
    KEY (UserID)
);

これを MyISAM を使用して保存すると、行の長さは固定形式を使用して 16 バイトになります。これは、100 万行ごとにデータ用に 16MB のスペースが必要であり、おそらくその半分がインデックス用に必要であることを意味します (使用するインデックスによって異なります)。これは非常にコンパクトであるため、ほとんどの場合、mysql はおそらくテーブルの作業部分全体をメモリ内に保持できます。

次に、最も一般的な操作に必要なインデックスを作成する問題です。たとえば、特定の時間範囲内のすべてのユーザーのイベントを常に表示する場合は、 に置き換えKEY (UserID)ますINDEX userbytime (UserID, Time)。次に、次のようなクエリはSELECT * FROM Events WHERE UserID=? AND Time BETWEEN ? AND ?非常に高速になります。

于 2012-05-18T04:15:41.697 に答える