【问题标题】:Most efficient way to set up MySQL Tables?设置 MySQL 表的最有效方法?
【发布时间】:2023-04-02 01:53:01
【问题描述】:

我有一个名为“用户”的表,其中包含诸如

username
DOB
gender
etc

每个用户都可以将他们的植物保存在一个名为“植物”的表格中,该表格包含以下字段

username
plant

所以用户 'johndoe' 会在表 'plants' 上显示如下:

johndoe -> lilly
johndoe -> orchid1
johndoe -> orchid2
johndoe -> fern1
johndoe -> fern2

问题:

这是设置我的表的坏方法吗?我问是因为当用户数量增加时,将会有数百行,其中有几行具有重复的用户名,因为每个用户可能拥有不止一种植物。这会减慢查询速度吗?

如果我为每个用户创建一个植物表,我认为这将显着增加数据库请求的数量并在数据库中创建大量表。

另一种选择是为 lilly、orchid、fern 等设置单独的表格,其中包含诸如

username

但我仍然会有几行重复的用户名。

有什么建议吗?

【问题讨论】:

    标签: mysql database


    【解决方案1】:

    规范化您的表格。向用户添加 id 字段并将该 id 存储在植物中而不是用户名中。

    此外,阅读更多关于 normalization principles 的信息并尝试在实践中应用它们。

    【讨论】:

    • (-0.5 次要尼特)您提出的不是标准化,而是可扩展性的良好做法。
    • 请在评论前阅读正常形式。说白了,没有两张表可以重复相同的数据。
    • 我当然做到了。他的用户名/植物表已经是第一范式。
    • 如果用户名是用户表的主键,那么这些表被规范化。规范化不是关于有一个 ID 列。
    • @raveren:假装你是全能的mysql之神并不好。没有人知道一切。
    【解决方案2】:

    我不会使用用户名,而是使用 INT id。像这样:

    userid
    username
    DOB
    gender
    etc
    

    对于您的植物:

    plantid
    userid_fk
    plantname
    

    然后加入 users.userid =plants.userid_fk 以查找匹配项:)

    【讨论】:

    • 你有理由吗?这似乎颠覆了数据库的正常形式。
    • 为什么植物表中的userid要加上后缀_fk?
    • @symcbean 表示它是外键。只是一个指示器,可以更轻松地阅读所有字段。
    【解决方案3】:

    这是一种非常合理的设置方式(您的初始建议);这就是relational databases 的用途。

    您正在植物表中建立经典的多对多关系。每个用户可以有几个工厂,每个工厂可以有几个用户。

    为了提高效率,您可以使用id 来指代您的用户,而不是用户名。在大多数关系数据库中,id 是一个行号,是一个非常有效(且紧凑)的引用。

    【讨论】:

      【解决方案4】:

      以下是我的处理方式,并带有一个示例数据库脚本和查询:

      创建/加载用户表 - 使用代理主键而不是用户名,因为对 INT 的查询会更快,而且它们可以改变。

      CREATE TABLE users  ( 
          id          int(11) AUTO_INCREMENT NOT NULL,
          username    varchar(255) NOT NULL,
          gender      char(1) NULL,
          PRIMARY KEY(id)
      ) ENGINE = MyISAM AUTO_INCREMENT = 3
      

      加载用户

      INSERT INTO users(id, username, gender)
        VALUES(1, 'john', NULL)
      GO
      INSERT INTO users(id, username, gender)
        VALUES(2, 'jane', NULL)
      GO
      

      创建植物

      CREATE TABLE plants  ( 
          id      int(11) AUTO_INCREMENT NOT NULL,
          name    varchar(200) NOT NULL,
          PRIMARY KEY(id)
      ) ENGINE = MyISAM AUTO_INCREMENT = 6
      

      装载植物

      INSERT INTO plants(id, name)
        VALUES(1, 'fern1')
      GO
      INSERT INTO plants(id, name)
        VALUES(2, 'fern2')
      GO
      INSERT INTO plants(id, name)
        VALUES(3, 'orchid1')
      GO
      INSERT INTO plants(id, name)
        VALUES(4, 'orchid2')
      GO
      INSERT INTO plants(id, name)
        VALUES(5, 'lilly1')
      

      创建联接表我在这里使用代理主键,因为许多网络平台无法正确更新具有 2 列主键的联接表。此外,我经常在这些类型的连接中添加元数据/详细信息,没有它会变得一团糟。注意我不限制同一用户添加同一植物类型的组合,但您可以轻松。

      CREATE TABLE plants_users  ( 
          id          int(11) AUTO_INCREMENT NOT NULL,
          plant_id    int(11) NOT NULL,
          user_id     int(11) NOT NULL,
          PRIMARY KEY(id)
      )
      ENGINE = MyISAM
      AUTO_INCREMENT = 8
      GO
      CREATE INDEX fk_plant_id USING BTREE 
          ON plants_users(plant_id)
      GO
      CREATE INDEX fk_user_id USING BTREE 
          ON plants_users(user_id)
      

      加载连接表

      INSERT INTO plants_users(id, plant_id, user_id)
        VALUES(1, 1, 1)
      GO
      INSERT INTO plants_users(id, plant_id, user_id)
        VALUES(2, 2, 1)
      GO
      INSERT INTO plants_users(id, plant_id, user_id)
        VALUES(3, 3, 1)
      GO
      INSERT INTO plants_users(id, plant_id, user_id)
        VALUES(4, 4, 1)
      GO
      INSERT INTO plants_users(id, plant_id, user_id)
        VALUES(5, 2, 2)
      GO
      INSERT INTO plants_users(id, plant_id, user_id)
        VALUES(6, 3, 2)
      GO
      INSERT INTO plants_users(id, plant_id, user_id)
        VALUES(7, 5, 2)
      

      最终查询:

      select
          users.username,
          plants.name
      from
          users,plants,plants_users
      where
          users.id = plants_users.user_id and
          plants.id = plants_users.plant_id
      

      结果:

          user    name
          john    fern1
          john    fern2
          john    orchid1
          john    orchid2
          jane    fern2
          jane    orchid1
          jane    lilly1
      

      【讨论】:

      • 感谢您的详细说明。一个问题:如果我使用与 PHP $_POST 绑定的方法,是否需要发布到所有 3 个表以保持更新?
      • 否 - 您只需将记录插入到plants_users 表中,您的请求变量应包含plant_id,您的会话变量应包含user_id。添加新用户或添加新类型的植物当然需要单独的 sql 查询。
      猜你喜欢
      • 1970-01-01
      • 2013-12-08
      • 2011-03-28
      • 1970-01-01
      • 1970-01-01
      • 2021-03-27
      • 1970-01-01
      • 2018-01-05
      • 1970-01-01
      相关资源
      最近更新 更多