WordPress数据库性能提升

WordPress表影响性能的表
wp_posts
wp_postmeta
wp_term_relationships
业务和表的关系
内容类型数据表
文章wp_posts
页面wp_posts
自定义文章类型wp_posts
附件wp_posts
导航菜单wp_posts
文章元数据wp_post_meta
分类目录wp_terms
标签wp_terms
自定义分类法wp_term_taxonomy
 

表间关系

数据表存储的数据关联到
wp_posts文章 页面 附件 版本 导航菜单项目wp_postmeta (通过post_id关联)
wp_postmeta文章的元数据wp_posts (通过 post_id关联)
wp_term_relationships文章 自定义分类法间关系

wp_posts (通过 post_id 关联)

wp_term_taxonomy (通过term_taxonomy_id 关联)

wp_term_taxonomy自定义分类法(默认类目录和标签)wp_term_relationships(通过 term_taxonomy_id关联)
wp_terms关联到分类法中的分类目录 标签 自定义分类项目wp_term_taxonomy (通过term_id 关联) 
wp_postmeta最慢   存放文章 页面 自定义内容wp_posts的元数据
元数据 包括 文章查看数 封面图片 自定义的字段 文章 wp_posts 对应 wp_postmeta
WordPress 把 wp_postmeta  设计成了一张纵表 且没有索引
横表和纵表 横表是项目最常用的
横表 STUDENT_SCORE 语文 英语成绩等7个KPI指标
mysql> SELECT * FROM STUDENT_SCORE;
    Id     CHINESE_SCORE ENGLISH_SCORE MATH_SOCRE PHYSICAL_SCORE SPORTS_SCORE CHEMICAL_SCORE BIOLOGICAL_SCORE
----------- ------------- ------------- ---------- -------------- ------------ -------------- ----------------
    10001      87.4       63     92       86      75       85        89
    10002       91             89         98             62      76       82        73
对应于纵表/竖表 7个KPI指标
SQL> SELECT * FROM STUDENT_SCORE;
Id               FieldName             Value
----------- --------------------- ----------
10001   CHINESE_SCORE       87.4
10001   ENGLISH_SCORE       63
10001   MATH_SOCRE             92
10001   PHYSICAL_SCORE     86
10001   SPORTS_SCORE        75
10001   CHEMICAL_SCORE    85
10001   BIOLOGICAL_SCORE 89
 
10002      CHINESE_SCORE       91
10002      ENGLISH_SCORE       89
10002      MATH_SOCRE             98
10002      PHYSICAL_SCORE    62
10002      SPORTS_SCORE        76
10002      CHEMICAL_SCORE    82
10002      BIOLOGICAL_SCORE 73

横表转成纵表/竖表,对应的记录会翻倍增长
对应于 大数据 表或宽表 有性能问题
WordPress 不根据 meta_id 去查 postmeta 表
是根据 post_id 去查  post  单个 meta 信息 或meta key 和 value
主键 meta_id  仅是个自增 ID
提升性能 是把 post_id 和 meta_key 改为主键 后根据 post_id 做分区表
两个好处
一查询 可根据 post_id 去读 分区表的数据 不用全表查找
一这俩字段组成唯一约束和索引了 查询速度会加快
WordPress 默认没有为 wp_postmeta 的表 设定 post_id 和 meta_key 的唯一约束
存在一个 post 再 postmeta 表有多个同样的的 meta key 和 value 的情况的
验证
SELECT * FROM  wp_postmeta pm WHERE  meta_id NOT IN (  SELECT max(meta_id) FROM  wp_postmeta pm2 where  pm2.post_id=pm.post_id and pm2.meta_key=pm.meta_key  )
SELECT distinct meta_key From wp_postmeta Group By post_id,meta_key Having Count(*)>1

返回内容

 WordPress 运行过程中产生的垃圾数据 可无副作用删除
 

删除掉重复的 meta key 和 value 记录 仅保留最新的一个

DELETE FROM  wp_postmeta WHERE meta_id  IN (
   select * from (
    select meta_id  FROM  wp_postmeta pm  WHERE meta_id NOT IN (
      SELECT max(meta_id) FROM  wp_postmeta pm2 where  pm2.post_id=pm.post_id and pm2.meta_key=pm.meta_key
     )
   ) as g1
)

问题是 WordPress 开启文章的版本控制情况下
插入重复 post 和 meta key 的情况的
数据库改成唯一约束后会报错
或者其它插件会这么做
解决办法是WordPress 里 Hook 一下 add metadata 函数
insert 前先 check 是否已经 exists
另外就是数据库里面加个 Trigger 做判断 如果已存在 就更新
数据清理完毕,那么可以开始建立分区表了
必须先 ADD UNIQUE(`meta_id`),才能 DROP meta_id 的 PRIMARY KEY
ALTER TABLE `wp_postmeta` ADD UNIQUE INDEX `UNQ_meta_id` (`meta_id` ASC);ALTER TABLE `wp_postmeta`  DROP PRIMARY KEY (`meta_id`);
再 DROP 掉 meta_id 的 UNIQUE
是因为后面分区 要求 RANGE 分区列的UNIQUE INDEX 必须包含所有primary key
即任意 UNIQUE INDEX 都要包含 post_id,meta_key 分区函数列
否则分区函数是无法创建
会报错误:Error Code: 1503. A UNIQUE INDEX must include allcolumns in the table's partitioning function
ALTER TABLE `wp_postmeta`  DROP UNIQUE INDEX `UNQ_meta_id` (`meta_id` ASC);
ALTER TABLE `wp_postmeta`  ADD PRIMARY KEY (`post_id`, `meta_key`);
ALTER TABLE `wp_postmeta`  CHANGE COLUMN  `meta_key`  `meta_key`  VARCHAR(255) NOT NULL ,
CHANGE COLUMN `post_id`  ` post_id` BIGINT(20) UNSIGNED NOT NULL ;
ALTER TABLE `wp_postmeta`
ADD UNIQUE INDEX `UNQ_post_id_meta_key` (`post_id` ASC, `meta_key` ASC),
ADD UNIQUE INDEX `UNQ_meta_id_post_id_meta_key` (`meta_id` ASC, `post_id` ASC, `meta_key` ASC);
好了  post 表 id  分布  从 id 从5万到22万
先给 posts 表分好区SELECT id FROM wp_posts order by id asc;
ALTER TABLE wp_posts PARTITION BY RANGE(id) (
   PARTITION p0 VALUES LESS THAN (60000),
   PARTITION p1 VALUES LESS THAN (70000),
   PARTITION p2 VALUES LESS THAN (80000),
   PARTITION p3 VALUES LESS THAN (90000),
   PARTITION p4 VALUES LESS THAN (100000),
   PARTITION p5 VALUES LESS THAN (110000),
   PARTITION p6 VALUES LESS THAN MAXVALUE
);
wp_postmeta 表 如法炮制
再查询 post 的 meta
不用全表扫描 只用扫分区内的数据了
且可以走索引
wp_term_relationships查询也比较耗时
把 object_id,term_taxonomy_id 改为主键后
也分区
ALTER TABLE wp_term_relationships PARTITION BY RANGE COLUMNS(object_id,term_taxonomy_id) (
  PARTITION p0 VALUES LESS THAN (60000,MAXVALUE),
  PARTITION p1 VALUES LESS THAN (70000,MAXVALUE),
  PARTITION p2 VALUES LESS THAN (80000,MAXVALUE),
  PARTITION p3 VALUES LESS THAN (90000,MAXVALUE),
  PARTITION p4 VALUES LESS THAN (100000,MAXVALUE),
  PARTITION p5 VALUES LESS THAN (110000,MAXVALUE),
  PARTITION p6 VALUES LESS THAN (MAXVALUE,MAXVALUE)
);
WordPress数据库频繁的调用
会拖慢网站整体的载入速度
减少 WordPress 数据库查询次数提升速度
在网页底部显示运行时 WordPress 数据库查询次数和内存使用情况
//放到主题function.php里既可 显示数据库查询次数、查询时间及内存占用的代码
function performance( $visible = false ) {
    $stat = sprintf(  '%d 次查询 用时 %.3f 秒, 耗费了 %.2fMB 内存',  get_num_queries(), timer_stop( 0, 3 ), memory_get_peak_usage() /1024/1024);
    echo $visible ? $stat : "<!-- {$stat} -->" ;
}
add_action( 'wp_footer', 'performance', 20 );
减少 WordPress 数据库查询次数
WordPress 的wp-config.php里基本的配置
define('COOKIE_DOMAIN', 'https://www.ruikeedu.com');
define('WP_HOME', 'https://www.ruikeedu.com');//设置地址而不是服务器检查,这将减少服务器查询
define('WP_SITEURL', 'https://www.ruikeedu.com');//优化文章修改历史:Post-Revisioning
define('AUTOSAVE_INTERVAL', 120);// 修改WordPress 编辑器自动保存时间间隔为120秒保存一次
define('WP_POST_REVISIONS', 5);//仅保留保留5个最近修改,也可以减小此数字但不能太低了
define('EMPTY_TRASH_DAYS', 7 );//7天后自动清空回收站根据情况设定
define( 'CORE_UPGRADE_SKIP_NEW_BUNDLED', true );//更新时跳过 wp-content 目录,增加更新效率
//通过剔除对模板路径和样式表路径的数据库查询提高站点的性能
define('TEMPLATEPATH', '/wp-content/themes/ruikeedu');
define('STYLESHEETPATH', '/wp-content/themes/ruikeedu');

指定cookies域
阻止子域名上请求静态内容的cookies不必要的传输
可以使用此定义告知WordPress只向非静态域发送cookies,这将会大大提高网站的性能
如果主机支持指定PHP使用的内存
还可以根据主机配置情况加入下面任一行代码
define('WP_MEMORY_LIMIT', '64M');
define('WP_MEMORY_LIMIT', '96M');
define('WP_MEMORY_LIMIT', '128M');

如过没有使用缓存插件
可以开启WP自带的缓存(Cache)功能并设置缓存时间
define('WP_CACHE, true); // 打开 WordPress 自带的缓存功能
define('ENABLE_CACHE', true); // 缓存开关
define('CACHE_EXPIRATION_TIME', 3600); // 缓存时间间隔

3.0后版本要开始缓存在/wp-includes/default-constants.php中开启
网站会经常请求向wordpress.com的服务器发送请求传送数据
运行效率就降低了很多
设置wp-config.php来屏蔽此类外部请求的发送
在wp-config.php添加
define('WP_HTTP_BLOCK_EXTERNAL', true);  //禁止WordPress程序发出对外请求
网站将无法对任何一个外部服务器发出请求
加速网站收录使用了ping功能,加上以上代码后ping功能将会失效
可以设置对外请求白名单即可解决ping失效问题
以百度ping为例
define('WP_ACCESSIBLE_HOSTS', 'ping.baidu.com');//仅允许 WordPress 向ping.baidu.com发送请求
如果博客本身已经集成了类似“微博同步”、“新浪博客同步发布博文”、“微信机器人”等等一些功能的请一定要慎重使用这个“禁止WordPress程序发出对外请求”