1

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

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

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

谢谢!

4

10 回答 10

3

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

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

于 2010-02-15T22:18:41.050 回答
3

我会创建一个user_meta包含三列的表:user_id, key, value.

于 2010-02-15T22:25:41.233 回答
0

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

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

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

但是为什么不使用这样的规范化user_variables表:

id  | user_id | variable_name | variable_value

?

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

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

于 2010-02-15T22:17:32.527 回答
0

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

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

于 2010-02-15T22:19:27.983 回答
0

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

于 2010-02-15T22:22:27.003 回答
0

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

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

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

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

于 2010-02-15T22:28:10.863 回答
0

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

试试看,你不会后悔的。

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

于 2010-02-15T22:29:23.160 回答
0

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

如果您想坚持使用关系数据库,请不要采取仅仅创建具有如此多字段的表的幼稚方法:

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 是用户。

于 2010-02-15T22:30:27.917 回答
0

您可能会考虑使用三重存储或键值存储而不是 MySQL ,这样您就可以获得所有多线程多用户、性能和缓存的好处,弄清楚了,而无需尝试提前弄清楚什么是麻烦您真正想要存储的值。

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

于 2010-02-15T22:53:27.060 回答
0

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

于 2010-02-16T02:12:39.557 回答