La base de datos grande causa una carga lenta

2

Tengo una base de datos de WordPress de 2GB (con InnoDB Storage Engine) y noté que mi sitio se carga lentamente cuando presiono el botón de publicación justo después de seleccionar una imagen destacada en la biblioteca de medios.

Eché un vistazo a mis tablas y noté que wp_postmeta es la tabla más grande y wp_posts la segunda más grande de todas las tablas.

¿Hay alguna manera de acelerar mi carga? La base de datos es InnoDB

    
pregunta Ruriko 11.03.2013 - 05:37

1 respuesta

5

RENUNCIA DE RESPONSABILIDAD: No es un desarrollador de WordPress, solo un DBA de MySQL

Hay una estructura de tabla especial en Oracle llamada Vista Materializada. Básicamente, se construye realizando una consulta ÚNICA (sin usar la cláusula WHERE) y almacenando el conjunto de resultados. Luego, simplemente SELECCIONE de ese conjunto de resultados estáticos en lugar de reconstruir cada resultado ÚNICO.

Primero, veamos las dos tablas:

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

Esto puede sonar bastante feo en el mundo de la base de datos, pero lo que se necesita sería un Producto Cartesiano que se manifestaría como una tabla regular.

Prepárate, esto va a ser bastante molesto ...

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;

Básicamente, todo y el fregadero de la cocina están en esta mesa. Usaría esta tabla para ejecutar sus consultas SELECT. ¿Alguna consulta no funciona bien? Solo agregue el índice necesario en el script y reconstrúyalo.

CAVEAT # 1

Este proceso valdría la pena siempre y cuando la tabla pueda reconstruirse fuera del horario laboral y esté disponible antes de que comience el día hábil. Puede hacer que la copia antigua esté disponible durante el proceso de reconstrucción ejecutándose de la siguiente manera:

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 tabla wp_posts_postmeta_joined debe ser MyISAM, independientemente de los motores de almacenamiento utilizados por wp_posts y wp_postmeta .

Agregué ROW_FORMAT=Fixed para aumentar la velocidad de lectura de la tabla 20-25%. Esta tabla puede ser bastante grande, así que asegúrese de tener el espacio en el disco. Escribí sobre esto de nuevo el 25 de marzo de 2011 .

¡Pruébalo!

    
respondido por el RolandoMySQLDBA 04.04.2013 - 19:22

Lea otras preguntas en las etiquetas