【问题标题】:Website: What is the best way to store a large number of user variables?网站:存储大量用户变量的最佳方式是什么?
【发布时间】:2011-01-17 04:16:47
【问题描述】:

我目前正在使用 PHP 和 MySQL 设计一个网站,随着网站的进行,我发现自己在 users 表中添加了越来越多的列来存储各种变量。

这让我想到,有没有更好的方法来存储这些信息?澄清一下,这些信息是全球性的,可能会受到其他用户的影响,因此 cookie 不起作用,如果他们清除 cookie,我也会丢失信息。

我的问题的第二部分是,如果事实证明将其存储在数据库中是最好的方法,那么拥有大量列或者将相关列组合成分隔的 varchar 列和然后用 PHP 分解它们?

谢谢!

【问题讨论】:

  • 谢谢!我将研究提到的其他数据库以及拆分数据库。不幸的是,标准化的 user_variables 表方法不起作用,因为我经常需要一次提取多个变量。对于某些人来说,我认为我可以将它连接成一个字符串,因为我几乎总是将它们放在一起并且我从不索引它们。再次感谢,只是想确保我没有遗漏一些明显的东西。

标签: php mysql variables store


【解决方案1】:

数据库是存储此类数据的绝佳场所,只要它们是变量而不是大型图像文件。该数据库具有存储和检索大量数据的所有优化和规范。您在文件系统级别上设置的任何内容都将永远被数据库在速度和功能方面已经拥有的东西所击败。

拥有大量列或者将相关列组合成分隔的 varchar 列然后在 PHP 中分解它们会更便宜吗?

维护问题相比,性能实际上并没有那么多 IMO - 管理数百列并不有趣。在TEXT 字段中存储此类数据(可能作为serialized 对象)是一个可行的选择——只要100% 确保您永远不必对该数据进行任何查询。

但为什么不使用这样的标准化user_variables 表:

id  | user_id | variable_name | variable_value

?

查询有点复杂,但提供了一个非常全面的干净表结构。您可以通过这种方式轻松添加任意用户变量。

如果您要进行大量查询,例如 SELECT FROM USERS WHERE variable257 = 'green',您可能必须坚持使用特定的列。

【讨论】:

    【解决方案2】:

    根据我的经验,我宁愿让数据库正确,也不愿开始添加包含多个项目的逗号分隔字段。必须筛选多个逗号分隔的字段只会损害程序的效率和代码的可读性。

    另外,如果您的表增长得太多,那么也许您需要考虑将其拆分为由外部依赖项连接的多个表?

    【讨论】:

      【解决方案3】:

      我不会选择将列组合在一起并分解它们。这是不整洁的工作,非常难以管理。相反,也许可以尝试将这些列分布在几个表上并使用 InnoDb 的事务功能。

      如果您仍然不喜欢频繁更新数据库的想法,并且此方法符合您想要实现的目标,您可以使用APC's caching function 在服务器上“全局”存储(缓存)信息。

      【讨论】:

        【解决方案4】:

        MongoDB(和它的 NoSQL 表亲)非常适合这类东西。

        【讨论】:

          【解决方案5】:

          我将创建一个 user_meta 表,其中包含三列:user_idkeyvalue

          【讨论】:

          • 虽然我喜欢这种方法的简单性,正如我之前所说,但我不确定它是否适用于需要大量数据的情况(大多数情况下)一次列(大多数情况下)。还是我弄错了?
          • 正确索引,像SELECT key, value FROM user_meta WHERE user_id=1 AND key IN ('homepage', 'background_color', 'arm_length', 'bacon_lover'); 这样的查询应该运行得很好。一旦它开始变慢,您可以考虑对数据库进行分区,其中 1-100,000 的用户在一个数据库上,100,001-200,000 的用户在另一个数据库上,依此类推。
          • 某处,E.F. Codd 在他的坟墓里翻了个身。
          • 这是一个非常适合 WordPress.com 的模型 - 一个非常庞大的数据库。
          【解决方案6】:

          数据库绝对是存储数​​据的最佳场所。 (我假设您正在考虑将其存储在平面文件中)使用数据库肯定会比存储在文件中获得更好的性能和安全性。

          关于将数据存储在多列或分隔它们...这是个人选择,但您应该考虑一些事情

          1. 如果您要分隔项目,您需要考虑用什么来分隔它们(在您的分隔文本中不太可能出现的东西)
          2. 我经常发现,尝试并想象一下与您水平相当的其他程序员是否能够在没有多少帮助的情况下理解您所做的事情会有所帮助。
          3. 是的,正如 Pekka 所说,如果您想对存储的数据执行查询,您应该坚持使用单独的列
          4. 如果您只需要几个信息字段,您也可以通过不每次都检索和解析所有数据来略微提升性能

          我建议使用单独的列,因为它为您提供了未来更大灵活性的选择。没有什么比彻底改变您的数据结构并将信息迁移到正轨更糟糕的了!

          【讨论】:

            【解决方案7】:

            我建议设置一个 memcached 服务器(请参阅http://memcached.org/)。许多大型网站已证明它是可行的。 PHP 有两个扩展将客户端集成到您的运行时中(请参阅http://php.net/manual/en/book.memcached.php)。

            试一试,你不会后悔的。

            编辑
            当然,这仅适用于经常使用的数据,否则必须一次又一次地从数据库中加载。请记住,您仍然需要将数据保存到某种持久性存储中。

            【讨论】:

            • 谢谢,我也会调查一下。
            【解决方案8】:

            您可能需要一个面向文档的数据库。

            如果您想坚持使用 关系 数据库,请不要天真地创建一个包含这么多字段的表:

            CREATE TABLE SomeEntity (
                ENTITY_ID    CHAR(10)    NOT NULL,
                PROPERTY_1   VARCHAR(50),
                PROPERTY_2   VARCHAR(50),
                PROPERTY_3   VARCHAR(50),
                ...
                PROPERTY_915 VARCHAR(50),
                PRIMARY KEY  (ENTITY_ID)
            );
            

            改为定义一个属性表:

            CREATE TABLE Attribute (
                ATTRIBUTE_ID  CHAR(10) NOT NULL,
                DESCRIPTION   VARCHAR(30),
                /* optionally */
                DEFAULT_VALUE /* whatever type you want */,
                /* end_optionally */
                PRIMARY KEY   (ATTRIBUTE_ID)
            );
            

            然后定义您的 SomeEntity 表,该表仅包含基本属性(例如,注册表中的必填字段):

            CREATE TABLE SomeEntity (
                ENTITY_ID   CHAR(10) NOT NULL
                ESSENTIAL_1 VARCHAR(30),
                ESSENTIAL_2 VARCHAR(30),
                ESSENTIAL_3 VARCHAR(30),
                PRIMARY KEY (ENTITY_ID)
            );
            

            然后为那些您可能想或不想存储的属性定义一个表。

            CREATE TABLE EntityAttribute (
                ATTRIBUTE_ID    CHAR(10) NOT NULL,
                ENTITY_ID       CHAR(10) NOT NULL,
                ATTRIBUTE_VALUE /* the same type as SomeEntity.DEFAULT_VALUE;
                                   if you didn't create that field, then any type */,
                PRIMARY KEY     (ATTRIBUTE_ID, ENTITY_ID)
            );
            

            显然,就您而言,SomeEntity 是用户。

            【讨论】:

              【解决方案9】:

              您可以考虑使用triplestorekey-value store 而不是 MySQL 通过这种方式,您将获得所有多线程多用户、性能和缓存的好处,弄清楚了,而无需尝试提前找出您真正想要存储什么样的值。

              缺点:计算出爱达荷州所有拥有帽子的人的平均工资会有点贵。

              【讨论】:

                【解决方案10】:

                取决于您存储的用户信息类型。如果它的会话相关数据,使用 php 会话与会话事件处理程序协调,将您的会话数据存储在数据库中的单个数据字段中。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2023-04-08
                  • 1970-01-01
                  • 2010-10-10
                  • 2011-10-14
                  • 2022-06-23
                  • 2011-11-26
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多