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


29

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

抄本中给出解释不详细:

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


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

Answers:


30

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

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

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

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

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

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


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

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

1
Denis您可以详细说明这一点,我觉得它很有用,但我喜欢一些数据,有人进行过测试吗?主要的缺点和局限是什么,谢谢。
Wyck

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

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

5

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

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

30,000个产品x每个40个meta = 1,200,000行 wp_postmeta

+

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

因此,仅使用30,000种产品,您就会看到其中有1,800,000行wp_postmeta

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

问题是双重的:

  • 使用MySQL进行自我联接非常昂贵
  • wp_postmeta除非您使用的是更高版本的mysql版本,否则不会对表建立索引(例如,没有FULLTEXT索引meta_value

举例说明:

SELECT meta_value FROM wp_postmeta WHERE meta_key LIKE '_shipping_city'

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

甚至主页也变得非常慢,因为主题从下拉菜单中拉出了各种元素wp_postmeta-滑块,一些插入的评论以及其他一些meta。通常,产品上市非常缓慢,上市产品时搜索也同样缓慢。

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

但是,一旦登录的用户尝试执行一些通常不执行的操作,或者当克朗,缓存插件或任何其他实用程序想要从数据库中获取实际数据以对其进行缓存或执行其他任何操作时,事情就变慢了。

所以我尝试了其他方法:

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

在此期间,我移动了附件 postmeta和所有其他帖子类型的元数据移动到了自己的表中。

然后我迷上了 get_(post_type)_meta过滤器以覆盖对元数据的检索,以从新的自定义表中为它们提供服务。

现在与之前的查询相同,大约需要3秒钟的时间才能从 wp_postmeta需要0.006秒钟。现在,该站点的行为就像是全新的WP安装一样。

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

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

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

在这种情况下,很难告诉打算拥有大量数据的人,并且-禁止使用该数据进行查询/搜索 wp_postmeta表。性能的提高将是巨大的。

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

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

您必须确保其他任何插件/附件开发人员都可以在检索数据之前和之后将其挂接到插件中以操作数据。如果您这样做的话,那么您将非常稳固。


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

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

2

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

但是,通常您可以将数据舒适地存储在现有的不同表中,并且存储数据的位置取决于插件的功能。

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

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


1

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

使用post meta来查询值的问题是当值是数组的值时,诸如此类:

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

这将作为序列化的字符串存储在数据库中,如下所示:

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

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

解决方案取决于项目,您将明白原因。如果您将数据存储为a,var = val则wp将能够进行搜索,而无需使用php来解压缩每个测试。为此,在上面的场景中,您将使用一些命名空间并存储元密钥:

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

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

希望这可以帮助某人


0

对于我的FarmVille网站:)我做到了,但从未完成,因为我卖了它:

  1. 我阅读了farmville xml并将数据转储到自定义表中
  2. 在WordPress中,我为该表中的每个字段自动创建了自定义字段(还有一些其他功能)
  3. 现在,担心表中或另一侧的值更改时会发生什么:自定义字段,因为它们需要连续同步

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

因此,这是同时使用两者的示例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.