web-dev-qa-db-fra.com

Une base de données volumineuse provoque une charge lente

J'ai une base de données WordPress de 2 Go (utilisant InnoDB Storage Engine) et j'ai remarqué que le chargement de mon site était lent lorsque j'appuyais sur le bouton de publication juste après avoir sélectionné une image sélectionnée dans la médiathèque.

J'ai jeté un coup d'œil à mes tables et j'ai remarqué que wp_postmeta était la plus grande table et wp_posts le 2e plus gros de toutes les tables.

Y a-t-il un moyen d'accélérer ma charge? La base de données est InnoDB

2
Ruriko

AVERTISSEMENT: Pas un développeur WordPress, juste un administrateur de base de données MySQL

Il existe une structure de table spéciale dans Oracle appelée vue matérialisée. Fondamentalement, il est construit en effectuant une requête JOIN (sans utiliser de clause WHERE) et en stockant le jeu de résultats. Ensuite, sélectionnez simplement dans cet ensemble de résultats statique plutôt que de reconstruire chaque résultat JOIN.

Tout d'abord, regardons les deux tables:

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

Cela peut paraître plutôt moche dans le monde des bases de données, mais il faudrait un produit cartésien qui se manifesterait sous la forme d'une table normale.

Préparez-vous, cela va être plutôt dérangeant ...

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;

En gros, tout et l’évier de la cuisine sont dans cette table. Vous utiliseriez cette table pour exécuter vos requêtes SELECT. Toute requête ne fonctionne pas bien? Ajoutez simplement l'index requis dans le script et reconstruisez-le.

CAVEAT # 1

Ce processus en vaut la peine tant que la table peut être reconstruite en dehors des heures de bureau et rendue disponible avant le début du jour ouvrable. Vous pouvez rendre l'ancienne copie disponible pendant le processus de reconstruction en exécutant la procédure suivante:

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;

CAVEAT # 2

La table wp_posts_postmeta_joined doit être MyISAM, quels que soient les moteurs de stockage utilisés par wp_posts et wp_postmeta.

J'ai ajouté ROW_FORMAT=Fixed pour augmenter la vitesse de lecture de la table de 20 à 25%. Cette table peut être assez grande, alors assurez-vous de disposer de l'espace disque. J'ai écrit à ce sujet le 25 mars 2011 .

Essaie !!!

5
RolandoMySQLDBA