草庐IT

mysql - 用户数据和更改日志的哪种布局最有效且存储消耗更少?

coder 2023-10-05 原文

我的用户可以更新他们的信息,这些信息保存在表中定义数量的列中,例如:user ( id INT, email VARCHAR, phone VARCHAR, address VARCHAR),例如.

我见过其他实现,例如 Wordpress 的实现,它为用户将此信息存储在一个名为 usermeta 的表中,其布局为 ( umeta_id INT, user_id INT, meta_key VARCHAR,元值 VARCHAR ).

在我想要实现的更改日志中,我正在评估是使用这样的解决方案还是制作(我认为会更好的)布局,例如:userLog ( id INT, date TIMESTAMP, email VARCHAR,电话 VARCHAR,地址 VARCHAR)
因此,我可以获得任何用户在给定日期拥有的所有信息的历史记录。行将只记录更改,在未更改的列上具有 NULL。

对于第一个问题:除了能够通过插入适当的meta_key来创建新的信息类型之外,这种布局还有什么优势吗?
我有时认为,如果我的环境需要考虑性能,那么这种布局可能不太合适,因为我会为我要存储的每种数据使用 VARCHAR

对于第二个问题:存储和选择/插入效率真的能影响我正在考虑的两种解决方案吗?
哪个解决方案比另一个解决方案占用空间更少(或更多)和/或选择/插入效率更低(或更高),为什么?

最佳答案

一些想法,如果不一定是答案:

显然更改日志对您来说是必不可少的,因此每个用户一行的原始结构不适合您。所以我们谈论的是以下选择:

  1. 每个用户的整个信息集的每个版本一行;或
  2. 每个用户信息项的每个版本一行

解决方案 1 对应于您的

userLog ( id INT, date TIMESTAMP, email VARCHAR, phone VARCHAR, address VARCHAR )

方案二对应Wordpress方案一:

umeta_id INT, user_id INT, meta_key VARCHAR, meta_value VARCHAR

您的问题 1: 我看不出 Solution2 有任何优势,除非您随后决定要捕获用户的(例如)网站 URL 或(例如)最喜欢的颜色作为好吧,你可以通过添加一个 meta_key 来做到这一点。但是您同样可以在 Solution1 下轻松地执行此操作,只需执行一个

ALTER TABLE userlog ADD COLUMN WebSiteURL(etc)

这并不难做到。除非您公司中的 DBA 非常像杜宾犬 (;))。因为您持有更改日志,所有现有用户(在更改时)现在将有一个空白的 WebsiteURL 列;但这正是您想要的:您不知道他们的 WebsiteURL,因为系统之前没有捕获它。当然,新列必须是 NULLABLE - 但无论如何这可能是不可避免的,即使使用“初始”数据,除非您用来捕获用户信息的方法坚持将电子邮件、电话和地址列为必需的列。

对我来说,meta_key 解决方案的缺点大于优点。缺点是:

  • 您必须开发一段数据透视代码,将一个用户的用户信息转换为另一个用户
    排。您必须在要在一行中获取用户信息的每个地方调用此代码。在 相比之下,Solution1只需要

    SELECT userID,[所有用户信息] FROM userLog INNER JOIN (SELECT userID,MAX(datechanged) AS LatestDAteChanged FROM userlog GROUP BY userID) a ON userlog.userid=a.userID AND userlog.DateChanged=a.LatestDAteChanged

    这比枢轴更有效。使用 UserID、DateChanged 的​​索引,这将 奔跑如风。

  • 除非您真的想在 userinfo 表(Email、Email、Email、Email、Email)中多次保存 meta_key 值,否则您需要一个额外的 Meta_Key_Lookup 表。

第二个问题: 对于最终的空间效率,是的,meta_key Solution2 是最好的。特别是如果您不使用 VARCHAR 元键,而是使用元键 ID 值,并且有一个单独的元键查找表(例如 1=Email,2=Phone 等)。但我认为这不是 meta_key 解决方案 2 的决定性论据,因为存储价格几乎为零,而且该解决方案涉及困难。

(注意/想法:恕我直言,您在解决方案 1 中保留 NULL 值的想法是一条错误的道路。尝试获取最新电子邮件的编码,然后是电话,然后是地址(分别) 对于每个用户来说,这将是一场噩梦:几乎与其他解决方案所需的枢轴一样难以编码/测试 - 以及服务器运行 - 以及存储边际的减少。每次做一件事时只保留整行变化。除非你只是举个例子,真正的用户信息集是 50 列宽...)

恕我直言,存储问题不是决定性的。那么让我们转向 SELECT/INSERT 效率:

在这个问题上,我认为还是Solution1胜出。在 Inserts 上,SOlution1 获胜:仅插入一行,即使用户更改了其信息中的每个字段。在 SELECTS 上,解决方案 1 再次获胜:您只需要查看每个用户的最新信息(上面的代码),这是 SQL 优化的类型。相比之下,解决方案 2 需要一个支点:SQL 不擅长的东西。

关于mysql - 用户数据和更改日志的哪种布局最有效且存储消耗更少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13364790/

有关mysql - 用户数据和更改日志的哪种布局最有效且存储消耗更少?的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  4. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  5. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  6. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  7. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  8. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  9. ruby - 更改 ActiveRecord 中对象的类 - 2

    假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。

  10. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

随机推荐