web-dev-qa-db-ja.com

データベースが大きいとロードが遅くなります

2GBのWordPressデータベース(InnoDBストレージエンジンを使用)を使用していますが、メディアライブラリで注目の画像を選択した直後に[公開]ボタンを押すと、サイトの読み込みが遅くなります。

私は自分のテーブルを見て、wp_postmetaが最大のテーブルで、wp_postsがすべてのテーブルのうち2番目に大きいテーブルであることに気付きました。

私の負荷をスピードアップする方法はありますか?データベースはInnoDBです

2
Ruriko

免責事項:WordPress開発者ではなく、MySQL DBAだけ

Oracleには、マテリアライズドビューと呼ばれる特別なテーブル構造があります。基本的に、JOINクエリを実行し(WHERE句を使用しない)、結果セットを格納することによって構築されます。次に、各JOIN結果を再構築するのではなく、単にその静的結果セットからSELECTを実行します。

まず、2つのテーブルを見てみましょう。

wp_postmeta

mysql> show create table wp_postmeta\G
*************************** 1. row ***************************
       Table: wp_postmeta
Create Table: CREATE TABLE `wp_postmeta` (
  `meta_id` bigint(20) unsigned NOT NULL auto_increment,
  `post_id` bigint(20) unsigned NOT NULL default '0',
  `meta_key` varchar(255) default NULL,
  `meta_value` longtext,
  PRIMARY KEY  (`meta_id`),
  KEY `post_id` (`post_id`),
  KEY `meta_key` (`meta_key`)
) ENGINE=MyISAM AUTO_INCREMENT=2926 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

wp_posts

mysql> show create table wp_posts\G
*************************** 1. row ***************************
       Table: wp_posts
Create Table: CREATE TABLE `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL auto_increment,
  `post_author` bigint(20) unsigned NOT NULL default '0',
  `post_date` datetime NOT NULL default '0000-00-00 00:00:00',
  `post_date_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
  `post_content` longtext NOT NULL,
  `post_title` text NOT NULL,
  `post_excerpt` text NOT NULL,
  `post_status` varchar(20) NOT NULL default 'publish',
  `comment_status` varchar(20) NOT NULL default 'open',
  `ping_status` varchar(20) NOT NULL default 'open',
  `post_password` varchar(20) NOT NULL default '',
  `post_name` varchar(200) NOT NULL default '',
  `to_ping` text NOT NULL,
  `pinged` text NOT NULL,
  `post_modified` datetime NOT NULL default '0000-00-00 00:00:00',
  `post_modified_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
  `post_content_filtered` text NOT NULL,
  `post_parent` bigint(20) unsigned NOT NULL default '0',
  `guid` varchar(255) NOT NULL default '',
  `menu_order` int(11) NOT NULL default '0',
  `post_type` varchar(20) NOT NULL default 'post',
  `post_mime_type` varchar(100) NOT NULL default '',
  `comment_count` bigint(20) NOT NULL default '0',
  PRIMARY KEY  (`ID`), KEY `post_name` (`post_name`),
  KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
  KEY `post_parent` (`post_parent`), KEY `post_author` (`post_author`)
) ENGINE=MyISAM AUTO_INCREMENT=59921 DEFAULT CHARSET=utf8

これはデータベースの世界ではかなり醜いように思えるかもしれませんが、必要とされているのは、通常の表として表されるデカルト積です。

自分自身をブレースしてください、これはどちらかといえば邪魔になるでしょう...

DROP TABLE IF EXISTS wp_posts_postmeta_joined;
CREATE TABLE wp_posts_postmeta_joined SELECT * FROM wp_posts WHERE 1 = 2;
ALTER TABLE wp_posts_postmeta_joined
    ADD COLUMN `meta_key` varchar(255) default NULL,
    ADD COLUMN `meta_value` longtext
;
ALTER TABLE wp_posts_postmeta_joined ENGINE=MyISAM;
ALTER TABLE wp_posts_postmeta_joined ROW_FORMAT=Fixed;
ALTER TABLE wp_posts_postmeta_joined
      ADD INDEX status_ndx (`ID`,`status`),
      ADD INDEX `post_name` (`ID`,`post_name`),
      ADD INDEX `type_status_date` (`ID`,`post_type`,`post_status`,`post_date`),
      ADD INDEX `post_parent` (`ID`,`post_parent`),
      ADD INDEX `post_author` (`ID`,`post_author`),
      ADD INDEX `id_meta_key`(`ID`,`meta_key`)
;
ALTER TABLE wp_posts_postmeta_joined DISABLE KEYS;
INSERT INTO wp_posts_postmeta_joined 
    SELECT A.*,B.meta_key,B.meta_value
    FROM wp_posts A LEFT JOIN wp_postmeta B
    ON A.ID = B.post_id
;
ALTER TABLE wp_posts_postmeta_joined ENABLE KEYS;

基本的に、すべてと台所の流しがこのテーブルにあります。このテーブルを使用してSELECTクエリを実行します。クエリがうまく機能しませんか。必要なインデックスをスクリプトに追加して再構築するだけです。

警告#1

このプロセスは、営業時間外にテーブルを休みの間に再構築して使用可能にすることができる限り価値があります。次のように実行すると、再構築プロセス中に古いコピーを利用可能にすることができます。

DROP TABLE IF EXISTS wp_posts_postmeta_joined_new;
CREATE TABLE wp_posts_postmeta_joined_new SELECT * FROM wp_posts WHERE 1 = 2;
ALTER TABLE wp_posts_postmeta_joined_new 
    ADD COLUMN `meta_key` varchar(255) default NULL,
    ADD COLUMN `meta_value` longtext
;
ALTER TABLE wp_posts_postmeta_joined_new ENGINE=MyISAM;
ALTER TABLE wp_posts_postmeta_joined_new ROW_FORMAT=Fixed;
ALTER TABLE wp_posts_postmeta_joined_new 
      ADD INDEX status_ndx (`ID`,`status`),
      ADD INDEX `post_name` (`ID`,`post_name`),
      ADD INDEX `type_status_date` (`ID`,`post_type`,`post_status`,`post_date`),
      ADD INDEX `post_parent` (`ID`,`post_parent`),
      ADD INDEX `post_author` (`ID`,`post_author`),
      ADD INDEX `id_meta_key`(`ID`,`meta_key`)
;
ALTER TABLE wp_posts_postmeta_joined_new DISABLE KEYS;
INSERT INTO wp_posts_postmeta_joined_new 
    SELECT A.*,B.meta_key,B.meta_value
    FROM wp_posts A LEFT JOIN wp_postmeta B
    ON A.ID = B.post_id
;
ALTER TABLE wp_posts_postmeta_joined_new ENABLE KEYS;
ALTER TABLE wp_posts_postmeta_joined RENAME wp_posts_postmeta_joined_old;
ALTER TABLE wp_posts_postmeta_joined_new RENAME wp_posts_postmeta_joined;
DROP TABLE wp_posts_postmeta_joined_old;

警告#2

テーブルwp_posts_postmeta_joinedは、wp_postsおよびwp_postmetaによって使用されるストレージエンジンに関係なくMyISAMであるべきです。

テーブルの読み取り速度を20〜25%向上させるためにROW_FORMAT=Fixedを追加しました。このテーブルはかなり大きくなる可能性があるので、ディスクスペースがあることを確認してください。 私は2011年3月25日にこの件について書きました

試してみる !!!

5
RolandoMySQLDBA