加速(缓慢的)巨大的 wordpress 数据库

Posted

技术标签:

【中文标题】加速(缓慢的)巨大的 wordpress 数据库【英文标题】:Speeding up a (slow) huge wordpress database 【发布时间】:2011-11-02 14:15:52 【问题描述】:

我正在测试一个涉及使用 wordpress 安装的新项目,该安装有超过 150 万个帖子,通常帖子内容/标题只有一两行 - 非常短。

我已经得到了强烈推荐的 W3-cache 插件,它有很大帮助 - 但是当你第一次登陆一个页面时,它需要 40-60 来加载并生成它的缓存,并且使用一个站点包含超过 100 万条帖子,我猜将它们全部缓存起来将是一场灾难——因为只有大约 5% 的帖子会被定期查看。

以下是帖子的标准构建发生了什么,我可以做些什么来改变/加快明显的瓶颈?我什至不确定 JOIN 在做什么?当然,所有需要发生的事情就是通过 ID 发布。花费了这么长时间的查询看起来像是一个查询,它显示了许多帖子并根据元数据对它们进行排序 - 我不需要在帖子页面上?

 [5] => Array
    (
        [0] =>  SELECT   wp_posts.* FROM wp_posts  INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) WHERE 1=1  AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish') AND (wp_postmeta.meta_key = 'wpfp_favorites' ) GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value+0 ASC LIMIT 0, 1
        [1] => 43.2097918987
        [2] => require, require_once, include, get_header, locate_template, load_template, require_once, wp_head, do_action, call_user_func_array, start_post_rel_link, get_boundary_post_rel_link, get_boundary_post, get_posts, WP_Query->query, WP_Query->get_posts, W3_Db->query
    )

[6] => Array
    (
        [0] => SELECT p.* FROM wp_posts AS p  WHERE p.post_date < '0000-00-00 00:00:00' AND p.post_type = 'post' AND p.post_status = 'publish'  ORDER BY p.post_date DESC LIMIT 1
        [1] => 7.29560852051E-5
        [2] => require, require_once, include, get_header, locate_template, load_template, require_once, wp_head, do_action, call_user_func_array, adjacent_posts_rel_link_wp_head, adjacent_posts_rel_link, get_adjacent_post_rel_link, get_adjacent_post, W3_Db->query
    )

[7] => Array
    (
        [0] => SELECT p.* FROM wp_posts AS p  WHERE p.post_date > '0000-00-00 00:00:00' AND p.post_type = 'post' AND p.post_status = 'publish'  ORDER BY p.post_date ASC LIMIT 1
        [1] => 1.78813934326E-5
        [2] => require, require_once, include, get_header, locate_template, load_template, require_once, wp_head, do_action, call_user_func_array, adjacent_posts_rel_link_wp_head, adjacent_posts_rel_link, get_adjacent_post_rel_link, get_adjacent_post, W3_Db->query
    )

[8] => Array
    (
        [0] => SELECT option_value FROM wp_options WHERE option_name = 'theme_mods_twentyeleven' LIMIT 1
        [1] => 1.00135803223E-5
        [2] => require, require_once, include, get_header, locate_template, load_template, require_once, wp_head, do_action, call_user_func_array, _custom_background_cb, get_background_image, get_theme_mod, get_theme_mods, get_option, W3_Db->query
    )

[9] => Array
    (
        [0] => SELECT option_value FROM wp_options WHERE option_name = 'mods_Twenty Eleven' LIMIT 1
        [1] => 8.82148742676E-6
        [2] => require, require_once, include, get_header, locate_template, load_template, require_once, wp_head, do_action, call_user_func_array, _custom_background_cb, get_background_image, get_theme_mod, get_theme_mods, get_option, W3_Db->query
    )

[10] => Array
    (
        [0] => SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('post_format') AND tr.object_id IN (1034759) ORDER BY t.name ASC
        [1] => 1.31130218506E-5
        [2] => require, require_once, include, get_header, locate_template, load_template, require_once, body_class, get_body_class, get_post_format, get_the_terms, wp_get_object_terms, W3_Db->query
    )

[11] => Array
    (
        [0] => SELECT DISTINCT post_author FROM wp_posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 2
        [1] => 1.31130218506E-5
        [2] => require, require_once, include, get_header, locate_template, load_template, require_once, body_class, get_body_class, apply_filters, call_user_func_array, twentyeleven_body_classes, is_multi_author, W3_Db->query
    )

[12] => Array
    (
        [0] => SELECT * FROM wp_posts  WHERE (post_type = 'page' AND post_status = 'publish')  AND ( ID <> 1232798 )    ORDER BY menu_order,wp_posts.post_title ASC
        [1] => 1.00135803223E-5
        [2] => require, require_once, include, get_header, locate_template, load_template, require_once, wp_nav_menu, call_user_func, wp_page_menu, wp_list_pages, get_pages, W3_Db->query
    )

[13] => Array
    (
        [0] => SELECT * FROM wp_users WHERE ID = 4031 LIMIT 1
        [1] => 2.00271606445E-5
        [2] => require, require_once, include, the_post, WP_Query->the_post, setup_postdata, get_userdata, W3_Db->query
    )

[14] => Array
    (
        [0] => SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('post_tag') AND tr.object_id IN (1034759) ORDER BY t.name ASC
        [1] => 1.78813934326E-5
        [2] => require, require_once, include, get_template_part, locate_template, load_template, require, post_class, get_post_class, get_the_tags, get_the_terms, wp_get_object_terms, W3_Db->query
    )

[15] => Array
    (
        [0] => SELECT * FROM wp_comments  WHERE comment_approved = '1' AND comment_post_ID = 1034759 ORDER BY comment_date_gmt ASC 
        [1] => 2.09808349609E-5
        [2] => require, require_once, include, comments_template, get_comments, WP_Comment_Query->query, W3_Db->query
    )

[16] => Array
    (
        [0] => SELECT post_id, meta_value, post_status FROM wp_postmeta LEFT JOIN wp_posts ON post_id=wp_posts.ID WHERE post_status='publish' AND meta_key='wpfp_favorites' AND meta_value > 0 ORDER BY ROUND(meta_value) DESC LIMIT 0, 5
        [1] => 1.50203704834E-5
        [2] => require, require_once, include, get_sidebar, locate_template, load_template, require_once, dynamic_sidebar, call_user_func_array, wpfp_widget_view, wpfp_list_most_favorited, W3_Db->query
    )

不管上述问题如何,我目前正在使用共享主机 - 所以显然它不会削减它,我想问的是你是否在哪里运行这种网站 - 什么样的服务器规格/主机您打算处理这种规模的安装吗?每周有几千名游客开始上升。

【问题讨论】:

你可以避开select *,换成select a, b 你能再解释一下吗?不确定你的意思 这没有帮助,我建议你包括执行计划结果(如果你明白我的意思) 【参考方案1】:

1) 在 WAMP 上使用 mysqltuner(您不能在没有 root 的情况下安装在共享主机上)来调整 MySQL 并更改查询缓存、内存等。这将对 WAMP 和最终的实时服务器产生巨大的影响。 https://github.com/rackerhacker/MySQLTuner-perl

2) 确保从数据库中删除帖子/页面修订。 WP 可以存储许多对数据库速度有很大影响的修订。在删除帖子/页面修订后,我发现数据库大小下降了 90%。

phpmyadmin 中作为 SQL 查询运行以删除修订;根据需要更改表前缀:

DELETE a,b,c FROM wp_posts a LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id) LEFT JOIN wp_postmeta c ON (a.ID = c.post_id) WHERE a.post_type = 'revision'

然后优化所有表。然后添加

define ('WP_POST_REVISIONS', FALSE);

靠近 wp-config.php 的顶部(在打开 &lt;?php ... 之后的某处)以禁用未来的修订。

3) 增加 php 和 WP 的内存以获得更好的性能:

将 php.ini 中的 memory_limit 行编辑为 128M:

memory_limit = 128M;

或者在 .htaccess 文件的顶部添加这一行:

php_value memory_limit 128M

如果这不起作用或引发错误,请在打开 &lt;?php 之后在 wp-config.php 文件顶部附近添加此行

define('WP_MEMORY_LIMIT', '128M');

4) 在最终的 VPS 上,配置 http.conf 以提高性能,并可能为 MySQL 服务器本身使用不同的框。

【讨论】:

不要在这么大的数据库上使用上面的 DELETE SQL 查询!很可能会破坏数据库中的有用关系。至少先备份你的数据库。【参考方案2】:

共享主机显然达到了性能极限。问题是硬件不足,而不是查询本身,所以您需要做的是为自己准备一台专用机器。这里的瓶颈似乎是 MySQL,它通常是磁盘绑定的,但是如果您的站点即将变得非常大,我会开始准备一些不同的架构,其中包含用于 HTTP 的负载均衡器和用于 MySQL 的强大机器(我认为 i7 有 12 gigs ram 并不太贵,如果您要使用单片数据存储,我会将它用于 MySQL 服务器)。

【讨论】:

谢谢,我会在 dedi 上启动它,看看它如何影响加载时间 - 感谢您的快速回复。 我会先在本地机器上设置它,然后再决定使用哪一个专用机器。使用 AB (ApacheBenchmark) 查看您的站点在特定负载条件下的行为。还要记住,您安装的所有软件 - 从 php 和 apache 到 mysql - 都必须正确配置才能在负载下工作。 干杯 - 嗯,我已经在 WAMP 上设置了它,但在我自己的机器 win7/4gb/2.5ghz 上它需要 3 倍的时间。知道为什么会这样吗?

以上是关于加速(缓慢的)巨大的 wordpress 数据库的主要内容,如果未能解决你的问题,请参考以下文章

优化wordpress给网站缓存数据加速-redis缓存器

如何找出为啥 wordpress 博客加载如此缓慢

缓慢的 WordPress 默认查询

开启硬件加速的 Android 页面转换缓慢

为啥模拟的 Parallel 函数在第一次运行时执行缓慢但随后加速?

缓慢的 WordPress 用户查询超过 7000 个用户