1

「訪問者」追跡スキーマが進行中です。プッシュすると、DB サーバーに負担がかかるようです。

VISITORS テーブルは、HASH (現在のレコード 310,000) によって一意のユーザーを識別します。ハッシュに対して検索が実行され、見つからない場合は追加されます。次の 2 つのテーブルには ID が必要です

CREATE TABLE  visitors (
    id int(10) UNSIGNED NOT NULL auto_increment,
    ip varchar(25) NOT NULL,
    hash varchar(64) NOT NULL,
    first_visit varchar(32) NOT NULL,
    created_at datetime NOT NULL default '0000-00-00 00:00:00',
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;   

ALTER TABLE visitors ADD UNIQUE INDEX (hash);
ALTER TABLE visitors ADD INDEX (created_at);

VISITOR_VISITS テーブルは、いくつかの参照ソース (現在のカウント 142,000) を特定できる場合にのみ、ユーザーがいつアクセスしたかを識別します。visitor_id、type、および visit_date を探して検索が実行されます。何も見つからない場合は追加されます。ID は次の表で使用されます。

CREATE TABLE  visitor_visits (
    id int(10) UNSIGNED NOT NULL auto_increment,
    visitor_id int(10) UNSIGNED NOT NULL,
    source varchar(64) NULL DEFAULT NULL DEFAULT NULL,
    medium varchar(64) NULL DEFAULT NULL,
    campaign varchar(256) NULL DEFAULT NULL,
    page varchar(32) NULL DEFAULT NULL,
    landing varchar(32) NULL DEFAULT NULL,
    type enum('fundraiser_view') NULL DEFAULT NULL,
    visit_date date NOT NULL default '0000-00-00',
    created_at datetime NOT NULL default '0000-00-00 00:00:00',
    PRIMARY KEY (id)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

ALTER TABLE visitor_visits ADD UNIQUE INDEX (visitor_id,type,visit_date);
ALTER TABLE visitor_visits ADD CONSTRAINT FK_visits_visitor_id FOREIGN KEY (visitor_id) REFERENCES visitors(id);

PAGE_VIEWS は、個々のページ ビューを記録します (すべてのページではなく、追跡しているページのみ)。それは訪問者にリンクすることができ、visitor_visit を参照することができます (現在のカウントは 240 万です -- 個々のページをログに記録した後にマイクロ訪問者のログ記録を開始したため、より高い理由です)。挿入/重複クエリを使用して、識別されたユーザーの view_date に基づいてこれにレコードを追加します。ID は必要ないため、純粋なルックアップ クエリは必要ありません

CREATE TABLE page_views (
  id int(10) UNSIGNED NOT NULL auto_increment,
  page_id int(10) UNSIGNED NOT NULL,
  current_donations decimal(10,2) NOT NULL DEFAULT 0,
  ip varchar(25) NOT NULL,
  hash varchar(32) NOT NULL,
  visitor_id int(10) UNSIGNED NULL DEFAULT NULL AFTER,
  visitor_visit_id int(10) UNSIGNED NULL DEFAULT NULL AFTER,
  page_views int(10) UNSIGNED NOT NULL DEFAULT 0,
  widget_views int(10) UNSIGNED NOT NULL DEFAULT 0,
  view_date date NOT NULL,
  viewed_at datetime NOT NULL default '0000-00-00 00:00:00',
  created_at datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

ALTER TABLE page_views ADD UNIQUE INDEX (page_id,view_date,visitor_id,hash);
ALTER TABLE page_views ADD INDEX (visitor_id);
ALTER TABLE page_views ADD INDEX (visitor_visit_id);
ALTER TABLE page_views ADD CONSTRAINT FK_page_views_page_id FOREIGN KEY (page_id)    REFERENCES pages(id);
ALTER TABLE page_views ADD CONSTRAINT FK_page_views_visitor_id FOREIGN KEY (visitor_id)    REFERENCES visitors(id);
ALTER TABLE page_views ADD CONSTRAINT FK_page_views_visit_id FOREIGN KEY (visitor_visit_id) REFERENCES visitor_visits(id);

先週、私たちのサイトはニュース記事のおかげで人が流入し、この訪問者はパフォーマンスのボトルネックを明らかにしました。そこに明らかな最適化があるかどうか疑問に思っています。それは外部キー制約でしょうか?オーバーインデックス?より良いインデックス作成が必要ですか?

4

2 に答える 2

0

データベースの何がボトルネックになっているのか教えてくれなかったので、InnoDB の同時書き込みだと思います。そうではなく、問題が SELECT のみにある場合 (私には疑わしい)、正確なクエリを表示する必要があります。ステージング テーブルを作成してからメイン テーブルにデータを一括移動することで、書き込みパフォーマンスの低下を抑えることができます。

CREATE TABLE page_views_tmp (
  id int(10) UNSIGNED NOT NULL auto_increment,
  page_id int(10) UNSIGNED NOT NULL,
  current_donations decimal(10,2) NOT NULL DEFAULT 0,
  ip varchar(25) NOT NULL,
  hash varchar(32) NOT NULL,
  visitor_id int(10) UNSIGNED NULL DEFAULT NULL AFTER,
  visitor_visit_id int(10) UNSIGNED NULL DEFAULT NULL AFTER,
  page_views int(10) UNSIGNED NOT NULL DEFAULT 0,
  widget_views int(10) UNSIGNED NOT NULL DEFAULT 0,
  view_date date NOT NULL,
  viewed_at datetime NOT NULL default '0000-00-00 00:00:00',
  created_at datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY (id)
) ENGINE=MEMORY DEFAULT CHARSET=utf8; 

そして、数秒に 1 回、またはこのテーブルにかなりの量の行が含まれた後に、次のようにします。

START TRANSACTION;

INSERT INTO page_views SELECT * FROM page_views_tmp;
DELETE FROM page_views_tmp;

COMMIT;
于 2012-06-22T09:46:42.277 に答える
0

これを試してください :: 1) varchar のインデックスはパフォーマンスをあまり改善しません。2) 日付範囲でテーブルを分割してみてください。

于 2012-06-20T18:03:38.713 に答える