【问题标题】:Storing variable name option in MySQL在 MySQL 中存储变量名称选项
【发布时间】:2021-04-17 23:03:17
【问题描述】:

假设您有一个包含大量用户的数据库,并且您需要存储随机数量的随机键值对。每个用户都可以有一组可变(非常可变)的对,并且密钥可以彼此完全不相关,但也可以重复。此外,键值对经常被写入,但大多数情况下,用户读取时会同时读取他们所有的键值对。每个用户的键值对可以达到数千个,但如上所述,它实际上可以是可变的(可以是 1,也可以是 1000)

到目前为止,我已经得出了三种可能的解决方案:

  1. 用户表中存储 JSON(或其他合适的序列化)的列,表示为该用户设置的键值对。可能是最好的阅读方式,但我担心插入
  2. 一个“keyvalue”表,其列包含用户 ID、键为 VARCHAR 和值。
  3. 两个表,一个称为“keyname”,key_id 为 INT,key_name 为 VARCHAR,以及从第 2 点开始的 keyvalue 表,但使用 key_id 而不是 key。

哪一个是 MySQL 中性能最好的(或者是否有比这些更好的选择)?哪些优化可以应用于数据库以使其更好地工作? (视图、索引等)

【问题讨论】:

  • EAV 看起来像合适的模式。 我担心插入 JSON_MERGE() 或 JSON_MERGE_PATCH()。
  • 您几乎列出了您拥有的选项(您缺少的选项是使用 nosql 解决方案,它更适合此类要求)。问题是:我们无法告诉您哪一个最适合您的特定要求和基础架构!您需要测试解决方案并选择最适合您要求的解决方案。您写道您担心 json 数据的插入。对其进行测试可以确认或反驳您的担忧,而不是依赖于人们的话语,他们可能对您的系统一无所知。

标签: mysql optimization


【解决方案1】:
CREATE TABLE kvs (
    user_id INT UNSIGNED NOT NULL,
    key VARCHAR(255) NOT NULL,
    val ? NOT NULL,
    PRIMARY KEY(user_id, key),
) ENGINE=InnoDB;

注意事项:

  • 由于 InnoDB 将 PK 与数据“聚集”在一起,给定用户的所有 k-v 对都是“连续的”,因此可以有效地获取。
  • 不需要AUTO_INCREMENT PK;你有一个合适的“自然”PK。
  • “值”可以是VARCHAR(255),或者,如果您需要更大的值,则可以是TEXT。 (还有其他选择,但这些似乎很有可能。)
  • key 不能是 TEXT 因为索引。如果您需要大密钥,则此模式将无法正常工作。请指定key 的要求。
  • 此架构可能最适合您描述的两个查询;如果有更多的查询,我可能需要调整。请注意,尤其是在 TEXT 中输入数字并期望它们进行数字比较是非常笨拙的。
  • 该模式假定“键值”的传统含义,即用户每个键只有一行。所以...

假设一个用户可以有重复的键,而且,一个键值对可以为一个用户重复:

CREATE TABLE kvs (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    user_id INT UNSIGNED NOT NULL,
    key VARCHAR(255) NOT NULL,
    val ? NOT NULL,
    PRIMARY KEY(user_id, id),  -- clustered on user_id, made unique via `id`
    INDEX(id)   -- to keep auto_increment happy
) ENGINE=InnoDB;

【讨论】:

  • 嗯,唯一的问题是每个用户的密钥可能重复,正如我写的那样
  • @Francexi - 如果val 不是太大,则使用PRIMARY KEY(user_id, key, val)
  • val 也可能重复。基本上,不应假定这些对以任何方式都是唯一的
  • @Francexi - 好的,我添加了另一个建议,基于重复行的可能性。如果我仍然不明白这个问题,请提供一些行示例,显示各种可能的重复不应允许的行示例(如果有)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-07
  • 2021-11-17
相关资源
最近更新 更多