为什么对 wp_postmeta 的引用如此缓慢?

Ric*_*mes 4 mysql indexing wordpress performance entity-attribute-value

在 WordPress 中获取属性(使用 MySQL)似乎比必要的要慢。

(这是一个自我回答的问题,所以继续我的回答。)

Ric*_*mes 9

标准模式wp_postmeta提供了较差的索引。这会导致性能问题。

通过将架构更改为此,对元数据的大多数引用将更快:

CREATE TABLE wp_postmeta (
    post_id …,
    meta_key …,
    meta_value …,
    PRIMARY KEY(post_id, meta_key),
    INDEX(meta_key)
) ENGINE=InnoDB;
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 当前AUTO_INCREMENT列浪费空间,并且因为它是PRIMARY KEY,所以会减慢查询速度,从而避免(post_id, meta_key).
  • 由于“集群”,InnoDB 进一步提高了该 PK 的性能。(我希望你不要还在使用 MyISAM!)
  • 如果您使用的是 MySQL 5.6(或 MariaDB 10.0 或 10.1),请meta_key从更改为VARCHAR(255),而不是VARCHAR(191)。(如果 191 不够,我们可以在一个单独的问题中讨论原因和解决方法。)
  • INDEX(meta_key) 是可选的,但如果您想“查找具有特定键的帖子”,则需要。
  • 警告:这些更改将加速postmeta 的许多用途,但不是全部。我认为它不会减慢任何用例。(如果您遇到此类查询,请提供此类查询。这可能是缓存问题,而不是真正的降级。)

如果你想展示你的 CREATE TABLE,我可以提供一个ALTER将它转换成这个。

如果您需要为一个帖子提供多个具有相同键名的元键,请使用此解决方案。它几乎和上面的建议一样好。

    meta_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,  -- keep after all
    ...
    PRIMARY KEY(post_id, meta_key, meta_id),  -- to allow dup meta_key for a post
Run Code Online (Sandbox Code Playgroud)

源文件

可能的 ALTER

注意事项:

  • 我没有办法测试这个。
  • 这不能解决 767 错误
  • meta_id是因为一些 WP 用户指出它被其他表引用。
  • 它假设您可能有多个行用于 (post_id, meta_key) 组合。(这似乎是糟糕的架构设计?)
  • 所有这些都加快了典型的SELECTs涉及 postmeta 的速度。
  • 这可能也适用于 woocommerce。
  • 如果您使用它,请转储您的数据库并准备好在出现问题时重新加载它。

SQL:

ALTER TABLE wp_postmeta
    DROP PRIMARY KEY,
    DROP INDEX post_id,
    ADD PRIMARY KEY(post_id, meta_key, meta_id),  -- to allow dup meta_key for a post
    ADD INDEX(meta_id);    -- to keep AUTO_INCREMENT happy
Run Code Online (Sandbox Code Playgroud)

  • @RickJames 和我有一个新的 WordPress 插件,GPL 且免费,用于处理 postmeta 和类似表的重新键入。https://wordpress.org/plugins/index-wp-mysql-for-speed/ (2认同)