在开发需要数据存储的插件时,使用一种或另一种方法的优缺点是什么?

法典中的解释未详述:


但是,在使用全新的表之前,请考虑是否将插件的数据存储在WordPress的Post
Meta(又称为“自定义字段”)中是否会起作用。 Post Meta是首选的
方法;尽可能/切实可行地使用它。


评论

仅供参考:MB Custom Table是一个插件,可以将元数据存储到自定义表中,而不是WP的post meta表中。

#1 楼

好吧,如果我戴着WP脚本小子的帽子,我的答案将是:始终使用post_meta。

但是,我碰巧知道有关数据库的一两件事,所以我的答案是:从不使用EAV(又称post_meta表)存储您可能需要查询的数据。

在索引方面,基本上没有值得在元表中使用的数据。因此,如果您要存储数据类型XYZ并希望查询所有具有XYZ且值为'abc'的帖子,那么...祝您好运。 (请参阅WP Trac中所有与用户/角色/上限相关的票证,以使您了解如何获得血腥感。)

在联接方面,您很快就陷入崩溃的极限。当存在多个连接条件时,优化器决定使用通用算法而不是分析查询。

,因此,不,不,不,不。永远都不要使用meta。除非您存储的是化妆品,否则绝不会成为查询条件的一部分。

它会分解到您的应用中。比方说,如果您要存储电影导演的生日,那可不是什么大问题。随便使用一个meta。但是,例如,如果要存储电影的发行日期,则不使用单独的表(或在posts表中添加列)并在该列中添加索引会很麻烦。

评论


是的,我正在开发的插件正在处理事件,新闻,新闻发布,工作机会等自定义数据……从“ WordPress World”之外,使用表并不是一个选择。但是WordPress Codex的建议有些令人困惑。序列化的数据块如何比规范化/结构化/索引数据更好?

–纳西夫·布尔吉(Nassif Bourguig)
2010-12-31 21:35

如果您询问一般的WP开发人员,他可能会回答“使用meta”或“使用分类法”。我同意,直到您需要对此进行查询为止。如果是这样,并且我相信这是您的情况,那么我唯一的答案是,将字段添加到posts表中,或者完全创建一个单独的表。否则,您会遇到查询方面的巨大性能问题,更重要的是,对于节点列表,还需要top-n排序。

–丹尼斯·伯纳迪(Denis de Bernardy)
2010-12-31 21:38

Denis您可以详细说明这一点,我发现它很有帮助,但是我希望能获得更多数据,有人进行过测试吗?主要的缺点和局限是什么,谢谢。

–维克
2010-12-04 6:49

@Denis-反对postmeta的热情倡导,是吗?您知道您坚决反对正统观念,如果您坚持这样的谈话,您就会从代码诗教会的大祭司的恩宠中掉出来,不是吗? :-)但是,您真的不认为自己夸大了一点吗?这实际上取决于是否会有成千上万的元记录。在许多情况下,根本没有足够的记录可担心。我正在部署的一个复杂站点大约有10,000个元记录,而计划的新记录很少,这很好(仅供参考,它不是博客)。

– MikeSchinkel
2010-12-04 8:52



@Denis-感谢您的评论。而且请不要误会我的意思,我可能更倾向于您的观点,但有以下几种结合:1.)与WordCamp伯明翰的Matt进行了长达一小时的辩论,讨论了Pod式字段的优点;以及2.)meta的简单性辞职后将注意力集中在我可能会改变的其他问题上。在WCB上,我意识到只要Matt负责就不会改变,因为(我的猜测是)Matt痴迷于较少的表的想法,以至于他无法识别768字节索引的不足之处键。 <叹>

– MikeSchinkel
2010-12-04 9:39



#2 楼

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

以WooCommerce为例,在拥有约30,000种产品的商店中,每个产品平均约40个帖子元(属性和所有内容),每个产品5个产品图片,这意味着每个图片将有〜4个图片元:

30,000个产品x 40个元wp_postmeta中的每个= 1,200,000行

+


30,000个产品x每个图像5个x每个x 4个图像元= wp_postmeta中的每个= 600,000行

您正在查看的产品只有30,000种,在wp_postmeta中有1,800,000行。

如果在产品或产品图片中添加更多属性,则此数字将成倍增加。

这是双重的:


使用MySQL进行自我连接非常昂贵。除非您使用的是更高版本的mysql版本,否则不对wp_postmeta表进行索引(即,对于meta_value没有FULLTEXT索引) )

T o从一个实际案例中给出一个示例:

SELECT meta_value FROM wp_postmeta WHERE meta_key LIKE '_shipping_city'


这会从所有订单详细信息中选择运送城市,即使在入门级专用服务器上也要花费约3秒的时间是5-10个订单。这是因为查询是从wp_postmeta表中运行的,该表在实时安装中有约300万行。

即使主页运行速度也很慢,因为该主题从wp_postmeta中提取了各种元素-滑块,一些评论插入内容,其他一些meta。通常,产品上市非常缓慢,上市产品时搜索也同样缓慢。

您无法通过任何常规方法解决此问题。您可以将Elastic Search放入服务器中,并在Wordpress中使用Elastic Search插件,可以使用redis / memcached,可以使用良好的页面缓存插件,但最终仍然存在基本问题-从-肿的数据中获取任何数量的数据只要完成,wp_postmeta表就会变慢。在我测试了下面实现的解决方案的服务器上,所有这些均已正确安装和配置并进行了优化,并且自从启动缓存插件以来,对于未登录的用户或经常执行的查询,站点都能正常运行。

但是当登录的用户尝试执行一些通常不执行的操作时,或者克隆人,缓存插件或任何其他实用程序想要从数据库中获取实际数据以对其进行缓存或执行其他任何操作时,事情进展缓慢。 br />
所以我尝试了其他方法:

我编写了一个小插件,将所有产品元数据(邮政类型产品的postmeta)带到由代码生成的自定义表格中。该插件将每个帖子的所有元数据都提取出来,并通过将每个元数据添加为列并将值插入到每一行中来创建表格。我将EAV格式转换为水平,平坦的关系格式。我还具有用于从wp_postmeta表中所有移动的产品中删除postmeta的插件。

,当我这样做时,我将附件postmeta和所有其他帖子类型的元数据移动到了自己的表中。 >
然后我迷上了get_(post_type)_meta过滤器,以覆盖元数据的检索,以便从新的自定义表中为它们提供服务。 0.006秒现在,该站点的行为就像是全新安装的WP。

...........

自然,以Wordpress方式做事更好。这实际上是规范。

但是,显而易见的是,EAV表的缩放效率非常低。它具有无限的灵活性,可以存储任何数据,但是为此付出的代价是性能。这是一个基本的权衡。

在这种情况下,很难告诉打算存储大量数据的人,而且-真是禁止-查询/搜索该数据以确保使用wp_postmeta表。性能的提高将是巨大的。

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

就像Easy Digital Downloads插件的创建者Pippin Williams提到的那样,如果他只是开始对插件进行编码,他将使用自定义表;如果您要创建将长期使用的东西,或堆积大量数据,如果设计得当,使用自定义表会更有效。

您必须确保其他任何插件/附件开发人员都具有在检索数据之前和之后钩入插件以操纵数据的方法。如果这样做,那么您就很扎实。

评论


有趣的东西!需要澄清的一件事是,提到的“ get_(post_type)_meta”过滤器实际上称为“ get_(meta-type)_metadata”,其中元类型可以是发布,评论或用户。因此,无论帖子类型如何,get_post_meta()都会通过get_post_metadata过滤器。过滤器的返回值就是您想要的最终元值。

– Berend
17年2月27日在6:03

get_(meta-type)_metadata->实际上,它适用于所有发布类型,并且确实访问的最终函数是get_post_metadata。但是,当您使用过滤器时仍然可以使用。

–unity100
17年2月27日在19:38

#3 楼

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

但是,通常您可以很舒适地将数据存储在现有的不同表中,数据的存储位置取决于什么您的插件确实可以使用。


对于常规插件设置,请使用get_option()API调用-该调用也会被缓存。
对于特定于单个帖子的插件设置,然后通过get_post_meta()使用每个帖子的自定义元数据。通常,这足以满足您的需求。

WordPress中实现了缓存,以加快响应速度。

#4 楼

丹尼斯100%同意。但是有一种解决方法。

将post meta用于要查询的值的问题是当值是数组的值时。例如:

array(
'key1' => 'val 1',
'key2' => 'val 2'
);


这将作为序列化的字符串存储在数据库中,看起来像这样:

{array["key1"]...{}...}


所以当您要查询所有帖子时使用array['key2'] = 'val 2',然后wp必须提取每个称为数组的元条目,将其解压缩,然后对其进行测试,然后转到下一个。如果您的站点成功并且有很多文章,页面,自定义文章等,这肯定会关闭您的服务器。

解决方案取决于项目,您将明白为什么。如果您将数据存储为var = val,则wp将能够进行搜索,而无需使用php来解压缩每个测试。要在上述情况下执行此操作,您可以使用一些命名空间并存储元密钥:

_array_key1 = 'val 1';
_array_key2 = 'val 2';


然后wp使用val 2查找密钥2将能够拉出它马上。不过这是项目。我当前的项目依赖于大约20种不同的dataTypes来存储每个自定义帖子,因此上述内容将创建一个庞大的表格进行搜索,这与我们预期的成百上千的帖子一样。因此,在这种情况下,自定义表是唯一的方法。

希望这对某人有帮助

#5 楼

对于我的FarmVille网站:)我做了这两个事情,但是都没有完成,因为我卖了它:


我阅读了farmville xml并将数据转储到自定义表中
在WordPress中,我已自动为该表中的每个字段(以及一些其他字段)自动创建了自定义字段
现在,您可以担心如果表中或另一侧的值发生更改会发生什么:自定义字段,因为它们需要不断同步

之所以这样做,是因为我一方面希望用户通过输入新的Farmville数据来编辑wordpress网站,例如从集成方面看,“一头母牛要花10个硬币”:如果现在xml更改,则这头母牛要花费“ 20个硬币”(通过前端编辑插件),之后将作为选项提供: XML OR用户是正确的(某种Wiki系统)。

所以这是同时使用两者的示例。