发布元数据与单独的数据库表

时间:2010-12-03 作者:Nassif Bourguig

在开发需要数据存储的插件时,使用这种或那种方法的利弊是什么?

这个explanation given in the codex 未详细说明:

然而,在开始创建一个全新的表之前,请考虑是否可以将插件的数据存储在WordPress的Post Meta(也称为自定义字段)中。后元分析是首选方法;尽可能/实际使用。

5 个回复
最合适的回答,由SO网友:Denis de Bernardy 整理而成

好吧,如果我戴上WP脚本的帽子,我的答案是:始终使用post\\u meta。

然而,我碰巧对数据库有一两点了解,所以我的答案是:永远不要使用EAV(又名post\\u元表)来存储您可能需要查询的数据。

在索引方面,基本上没有值得在元表中使用的内容。因此,如果您正在存储数据类型XYZ,并且希望查询所有具有XYZ值的帖子\'abc\', 好祝你好运(请参阅WP trac中所有与用户/角色/caps相关的票证,让您了解它会有多血腥。)

在连接方面,当存在多个连接条件时,您很快就会遇到优化器决定使用通用算法而不是分析查询的限制。

因此,不,不,不,不。永远,永远,永远,永远不要使用meta。除非您存储的内容是修饰性的,并且永远不会成为查询条件的一部分。

它会分解到你的应用程序。比如说,如果你在存储电影导演的生日,那就没什么大不了的了。你想用什么就用什么。但是,如果要存储电影的发布日期,那么不要使用单独的表(或向posts表添加列)并向该列添加索引,这将是愚蠢的。

SO网友:unity100

如果您的插件将包含大量数据,那么使用wp_postmeta 不是一个好主意,如下所示:

以WooCommerce为例,在一个拥有约30000种产品的商店中,每个产品平均会有约40个post meta(属性和所有内容),每个产品有5个产品图像,这意味着每个图像将有约4个图像元:

30000个产品x 40个meta每个=1200000行wp_postmeta

+

30000个产品x每个5个图像x每个4个图像元=600000行wp_postmeta

因此,仅使用30000种产品,您就可以看到1800000行wp_postmeta.

如果您为产品或产品图像添加更多属性,此数字将成倍增加。

这有两个问题:

MySQL的自连接非常昂贵wp_postmeta 除非您使用的是更高版本的mysql(即没有全文索引meta_value)从实际案例中给出一个示例:

SELECT meta_value FROM wp_postmeta WHERE meta_key LIKE \'_shipping_city\'
这将从所有订单详细信息中选择发货城市comes at a whopping ~3 seconds on an entry level dedicated server even if there are 5-10 orders. 这是因为查询是从wp_postmeta 在带电安装中约有300万行的表。

甚至主页也很慢,因为主题从wp_postmeta - 滑块,一些评论插入,一些其他元。一般来说,产品列表非常慢,在列出产品时,搜索速度也同样慢。

您无法通过任何正常方式修复此问题。您可以在服务器中使用弹性搜索,并在Wordpress中使用弹性搜索插件,您可以使用redis/memcached,您可以使用良好的页面缓存插件,但最终基本问题仍然存在——从臃肿的wp_postmeta 无论何时完成,桌子都会很慢。在我测试下面实现的解决方案的服务器上,所有这些都已正确安装和配置并进行了优化,自缓存插件启动以来,对于未登录的用户或通常进行的查询,站点运行良好。

但是,当登录用户尝试做一些通常不做的事情,或者cron、缓存插件或任何其他实用程序想要从db获取实际数据以缓存它或做其他事情时,事情就变得非常缓慢。

所以我尝试了其他方法:

我编写了一个小插件,以获取所有产品元(Posteta为post类型product) 到由代码生成的自定义表。这个插件为每个帖子获取所有元,并通过将每个元添加为列并将值插入到每一行来创建一个表。我将EAV格式转换为水平、扁平的关系格式。我还有一个插件,可以从wp_postmeta 桌子

当我这么做的时候,我搬家了attachment Posteta和所有其他post类型的meta都将添加到自己的表中。

然后我迷上了get_(post_type)_meta 筛选以覆盖元数据的检索,从而从新的自定义表中为元数据提供服务。

现在,来自早期的同一个查询,从中提取大约需要3秒钟wp_postmeta 大约需要0.006秒。该站点现在的行为就像是一个新的WP安装。

....................

当然,用Wordpress的方式做事更好。这实际上是常态。

However, 很明显,EAV表在扩展方面效率很低。它具有无限的灵活性,允许您存储任何数据,但您为此付出的代价是性能。这是一个基本的权衡。

在这种情况下,很难告诉某人谁打算拥有一大堆数据,并且——但愿如此——查询/搜索要使用的数据wp_postmeta 当然是表。这次演出一定会很精彩。

使用自定义表将允许您的数据堆积起来,并且仍然保持足够快的速度。

就像Pippin Williams,Easy Digital Downloads插件的创建者提到的那样,如果他刚开始编写插件,他会使用自定义表。如果你要创建一些可以长期使用或积累大量数据的东西,如果你设计得好,使用自定义表会更有效。

您必须确保任何其他插件/加载项开发人员都有方法连接到您的插件中,以便在检索数据之前和之后操作您的数据。如果你这样做,那么你就相当可靠了。

SO网友:Dan Smart

这取决于你在做什么。WP的方法是使用现有的表,因为它们被设计得足够灵活,但是偶尔您会遇到无法放置在现有表中的新数据类,例如,如果您需要类别元数据,您可以选择创建WP\\U termsmeta表。

然而,通常您可以将数据轻松地存储在现有的不同表中,存储数据的位置取决于插件的功能。

对于常规插件设置,请使用get_option() API调用-这也将被缓存get_post_meta(). 这通常足以满足您的需要

SO网友:Daithí

完全同意丹尼斯的意见。但这是有办法的。

对要查询的值使用post meta的问题是,当值是数组的值时,等等。例如:

array(
\'key1\' => \'val 1\',
\'key2\' => \'val 2\'
);
它以序列化字符串的形式存储在db中,如下所示:

{array["key1"]...{}...}
所以当你想用array[\'key2\'] = \'val 2\' 然后,wp必须提取每个名为array的元条目,将其解压缩,然后对其进行测试,然后转到下一个。如果你的网站成功了,并且有很多帖子、页面、自定义帖子等,这肯定会让你的服务器宕机。

解决方案取决于项目,您将看到原因。如果要将数据存储为var = val 然后,wp将能够搜索,而无需php来解包每个测试。要在上述场景中执行此操作,您需要使用一些名称空间并存储元键:

_array_key1 = \'val 1\';
_array_key2 = \'val 2\';
然后,wp使用val 2查找键2将能够直接将其拔出。这取决于项目。我当前的项目依赖于每个自定义帖子存储大约20种不同的数据类型,因此上面的内容只会创建一个庞大的表来搜索,就像我们所期望的100个成千上万的帖子一样。因此,在这种情况下,自定义表是唯一的方法。

希望这对某人有帮助

SO网友:edelwater

对于我的FarmVille网站:)我都做了,但从来没有完成,因为我卖掉了它:

我读取了farmville xml并将数据转储到WordPress中的一个自定义表中,我为该表中的每个字段自动创建了自定义字段(以及一些额外的字段),现在我担心如果表中或另一端的值发生变化会发生什么:自定义字段因为它们需要持续同步,所以我这样做是因为一方面我希望有用户通过输入新的farmville数据来编辑wordpress站点,例如“一头牛要花10个硬币”,但从集成的角度来看:如果xml元素发生变化,那么这头牛现在要花“20个硬币”(通过前端编辑插件),这将作为后面的选项提供:这样xml或用户都是正确的(类似于wiki系统)。

这里有一个同时使用两者的例子。

结束

相关推荐

Corrupt Wordpress Database

我认为这是最奇怪的文字印刷问题。一个拥有大量帖子数据库的客户网站已经有了自己的想法。前一分钟一切似乎都很好,接下来的帖子、类别和标签都不见了。此时仪表板告诉我9个类别中有2309个帖子,但当我单击admin中的categories链接时,列表中没有任何帖子。我可以在admin中看到所有帖子,但尽管它们过去被分配到类别并列出标签,但现在它们都“未分类”,没有标签。很明显,wordpress数据库在某种程度上已经损坏,但从哪里开始尝试修复呢!?以下是我迄今为止测试的内容:插件–我关闭了所有当前的插件。主题–我