为啥 Wordpress 有单独的 'usersmeta' 和 'users' SQL 表。为啥不把它们结合起来?

Posted

技术标签:

【中文标题】为啥 Wordpress 有单独的 \'usersmeta\' 和 \'users\' SQL 表。为啥不把它们结合起来?【英文标题】:Why does Wordpress have separate 'usersmeta' and 'users' SQL tables. Why not combine them?为什么 Wordpress 有单独的 'usersmeta' 和 'users' SQL 表。为什么不把它们结合起来? 【发布时间】:2012-06-15 21:11:47 【问题描述】:

除了 users 表,Wordpress 还有一个包含以下列的 usersmeta 表

meta_id user_id meta_key(例如名字) 元值(例如汤姆)

每个用户在 usersmeta 表中有 20 行,无论这些行是否有填充的 meta_value。也就是说,将始终存在的元行添加到 users 表不是更有效吗?

我猜测 users 表中的信息被更频繁地查询(例如 user_id、username、pass),因此保持这些行更小更有效。这是真的?这种表格分离还有其他原因吗?

【问题讨论】:

我猜他们想支持任意数量的元键? @Mike 但是他们不能从用户表中添加/删除相同的键吗?例如。当他们创建一个新的元键时,在当前结构中,他们必须在 usersmeta 表中为每个用户插入一个新行。如果元键都在用户表中,那么他们只需在整个表中添加一个新列。我可能遗漏了一些东西,但两者都支持任意数量的元键,不是吗? 也许meta_key 可能有 500 个不同的可能值,但大多数用户只有少数几个。他们不希望用户表上有 500 列。此外,也许不同的插件可以将元数据存储在用户身上,而您不希望修改您的数据库模式。真的,我无法推测。也许更多是 Wordpress 专家的人会加入。 @Mike 500 列似乎没有问题的原因是,到目前为止,每个用户在元表中的行数相同,无论是否有相应的值。因此,对于 500 个元键,它们在元表中仍然有 500 行,或者在用户表中有 500 列(如果它们被组合的话)。但我什至没有考虑第二部分。将行添加到元表的插件比让它们更改数据库结构更有意义。我认为很可能就是这样。 【参考方案1】:

这确实是一个关于数据库规范化的问题。您可以在许多地方查找有关该主题的信息。

基本答案 由于有大量关于此的文献,并且存在很多差异,我将仅举一些例子说明为什么会发生这种情况 - 归结为权衡;速度与存储要求,或易用性与数据复制。效率是多维的,由于 wordpress 做了很多不同的事情,可能有各种原因将它们分开 - 空间可能是一个问题,查询速度可能取决于此,可能更容易只查看元表而不是出于某些目的使用整个表格,反之亦然。

进一步阅读 这是一个深奥的话题,您可能想了解更多信息 - 关于这些问题有数百本书和数千篇学术论文。例如,看看这个关于设计数据库的先前 SO 问题: Database design: one huge table or separate tables?,或者这个:First-time database design: am I overengineering? 或 Database Normalization Basics About.com。

【讨论】:

【参考方案2】:

实体属性值

它被称为Entity Attribute Value (EAV) 数据模型,允许将任意数量的属性分配给给定的实体。这意味着每个用户可以有任意数量的元数据条目。

为什么要使用它

默认情况下,wordpress 设置了几个键(问题中说明了 20 个),但可以有任意数量。如果所有用户都有一千个元数据条目 - 每个用户的 usermeta 表中只有一千个条目 - 它没有(就数据库结构而言)用户可以拥有的元数据条目数量的限制.它还允许一个用户拥有一千个元数据整体,而所有其他用户拥有 20 个并且仍然有效地存储数据 - 或其任何排列。

除了灵活性之外,使用这种结构还允许主用户表保持较小 - 这意味着更有效的查询。

替代方案

使用 EAV 的替代方法包括:

每当属性数量发生变化时修改架构 将所有属性存储在序列化字符串中(在用户对象上) 使用无模式数据库

权限是第一点的最大问题,授予全面访问权限以更改数据库表的架构并不是一个好主意,并且对于许多(如果不是大多数)wordpress 安装(托管在 wordpress 上)来说是一个(理智的)障碍.com 或在 db 用户没有更改权限的共享主机上)。 mysql 也有一个硬限制4096 columns and 65,535 bytes per row。尝试在单个表中存储大量列最终会失败,同时创建查询效率低下的表。

将所有属性存储在序列化字符串中会使通过元数据值查询变得困难且缓慢。

Wordpress 与 mysql 密切相关,因此更改数据存储不是一个现实的选择。

更多 WP 信息

如果您不使用任何/许多插件,您可能会在每个用户的 usermeta 表中拥有恒定数量的行,但通常您添加的每个插件可能需要为用户添加元数据;添加的数字可能不是微不足道的,并且此数据存储在 usermeta 表中。

add_meta_user 的文档可能会更清楚地说明数据库为何采用这种结构。如果你把这样的代码放在某处:

add_user_meta($user_id, "favorite_color", "blue");

它将在 usermeta 表中为给定的 user_id 创建一行,而无需向主 users 表添加列 (favorite_color)。这使得通过最喜欢的颜色找到用户变得很容易,而无需修改 users 表的架构。

【讨论】:

很好的答案 AD7。我只想补充一点,如果你写了一些添加 favorite_color 的东西,如果编辑他们的页面,它可能会自动为每个定义的用户添加行,即使他们没有触摸颜色字段

以上是关于为啥 Wordpress 有单独的 'usersmeta' 和 'users' SQL 表。为啥不把它们结合起来?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的网站右侧有空格? (WordPress)

为啥 wordpress 会覆盖引导程序?

WordPress Woocommerce中具有单独价格的产品项目

为啥我的wordpress没有主题安装选项?

为啥 Wordpress 会创建一个巨大的 error_log 文件?

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