80个3列行或1 81列行

时间:2010-10-07 04:41:29

标签: sql mysql

我有一些数据需要存储,

我必须为每个用户存储这些数据,

数据或多或少

key: 0  
value: 107,

key: 1  
value 213

每个用户大约有80个键/值集

所以我的问题是,

我有一行基本上是

user_id key1, key2... key80

或者我有80行

user_id, key, value

<小时/> 我必须存储的数据:
您可以在此处查看我必须存储的实际数据: http://219.89.41.169/ReachApi/?gt=The%20hailwood

我不能复制/粘贴大约8mb的数据,因此页面可能需要一段时间才能加载。

但是你可以看到我得到了那种格式的数据, 因此,为什么我必须这样存储它。

5 个答案:

答案 0 :(得分:2)

您应该使用第一种方法 - 一行

user_id | key | value

这样,当您需要更多/更少的每个用户密钥时,您就会更灵活。

答案 1 :(得分:2)

我通常会想到表中的81列。但是,IF:

  • 键/字段的数量不太可能改变,AND
  • 所有字段都直接与用户相关,并适用于每个用户和/或
  • 您可能需要为给定用户一次查询多个密钥

那么拥有那么多列比将每个用户/键组合存储为自己的行更有意义。您可以获得类型安全性,更好地约束和索引数据的能力,并且您可以查询用户的统计数据而无需十几个连接(或者返回一堆必须然后组装成数据结构的行)。 p>

如果字段的数量不断变化,或者字段不适用于所有人(即:某些用户将拥有不同数量的字段),或者您永远不想知道超过用户3225的字段53的值,然后用户/键/值表更有意义。但是要保持一切正确,更新将永远需要(因为索引需要重做,而且你需要索引),这将是一个痛苦的问题,如果你有任何问题,查询将变得可怕一次只需要一个或两个以上的领域。

答案 2 :(得分:2)

我看了看数据。为什么要考虑将数据存储在数据库中?我想你想读取数据,在其上运行一些算法,并计算结果,对吗?或者它实际上是永久存储数据的要求,或者这甚至是你想要做的所有事情?

您列出的所有内容似乎都具有以下格式:

[KillsByEnemyTypeClass] => Array
                    (
                        [0] => stdClass Object
                            (
                                [Key] => 0
                                [Value] => 0
                            )
                        ...


[MedalCountsByType] => Array
                    (
                        [0] => stdClass Object
                            (
                                [Key] => 0
                                [Value] => 0
                            )

正如数据格式所暗示的那样,列表是连续的数组,而不是实际的键值对。由于键都是连续的,因此您可以使用所选的编程语言将值存储在一个大型数组中。

这是您的数据格式:

struct Data {
    std::string reason;
    int status;

    struct AiStatistics {
         int aDeathsByDamageType[82];
         int nHopperId;
         int aKillsByDamageType[82];
         int nMapId;
         double fMedalChestCompletionPercentage;
         int aMedalCountsByType[128];
         int nTotalMedals;
         int nVariantClass;
         ...
    } aaistatistics[9]; 
}

看起来阵列必须具有静态大小,因为82种不同的伤害类型可能对你有意义。如果突然有83种伤害类型,生成此数据的程序将发生变化,您也必须调整算法。这意味着数据和您的程序不是独立的,使用数据库的优势是值得怀疑的。

<强>更新

感谢您澄清您的要求。我理解为什么你现在必须为其他客户端缓存数据。

但是:您链接的数据是否必须存储的所有数据?这意味着,您是否只缓存来自Web API的输出,如果输出更改,则覆盖以前存储的数据?或者是否存在时间维度,并且您希望存储API的输出序列?在这两种情况下,围绕二进制数据的瘦C ++ API可能比数据库更有效。

如果仅用于缓存数据,我仍然建议在上面的对象模型之后对数据库进行建模。 AI Statistics表每个成员变量有一列,即完整的DeathsByDamageType数组的一列。将整个数组存储为一个值。客户端无法使用此模型查找单个值,但必须接收完整的数组。除非你有其他任何具体的用例,否则我会坚持这一点。您的数据库将更加简单。

如果这真的,真的,真的不够用于你的目的,你的表可能是:

table Data { id, reason, status }
table AiStatistics { id, data_id, ..., all integer members like nTotalMedals etc }
table DeathByDamageType { aistat_type, index, value }
table ... for every other array member of AiStatistics

默认情况下,以这种方式存储DeathByDamageType实际上是空间效率低的,表格至少是数组值的三倍,因为对于每个值,您必须分别存储AiStatistics引用ID和数组索引。

如果你这样做,至少利用数组中的稀疏性并且不要将DeathByDamageType中的值存储为0.你不能对数组执行此操作。

答案 3 :(得分:1)

我会远离数据库表中的81列,特别是对于这样的事情,您将来可能会添加更多“键”(在这种情况下,您需要向表中添加更多列)。

“键值”表可能会导致性能问题,并使编写查询变得笨拙,所以看看你是否能以某种方式将键分组到相关的部分中可能是有利的,你可以将它们填充到更小,更具体的部分中表。

答案 4 :(得分:1)

Pro 80 colums

  • 一次插入用户创建,只更新语句进行修改
  • 可以使用简单的SELECT语句(不使用自联接)来比较两个或多个键的值
  • O / R映射只是开箱即用
  • 数据库可以处理类型检查

Pro 80行

  • 添加密钥只是一个插入,不需要ALTER TABLE(如果您拥有大量用户,这意味着更新需要很长的停机时间
  • 插件可以轻松添加自己的配置设置(假设键名中有某种前缀以避免冲突)

关于80行的评论

  • 如果您使用此方法,我建议使用“key_id”而不是“key”,并为键提供第二个表,以便验证密钥名称。该表可以有第三列文档。