我有一个使用 Laravel 框架构建的应用程序。其功能之一是能够在表之间创建多态关系。它通过存储相关表的 ID 和相关表模型的完全限定类名来实现此目的。正如您可以想象的那样,某些条目可能会很长,具体取决于模型的命名空间和类名称。
在我的场景中,我有 4 个表。基表 A
是多态的。表 B
、C
和 D
不是。
非多态表模型的类名称如下:
LongNamespace\SubNamespace\Something\B
LongNamespace\SubNamespace\Something\C
LongNamespace\SubNamespace\Something\D
表A
的结果如下所示:
id | relation_id | relation_type
--------------------------------
1 | 1 | LongNamespace\SubNamespace\Something\B
2 | 2 | LongNamespace\SubNamespace\Something\C
3 | 5 | LongNamespace\SubNamespace\Something\D
4 | 12 | LongNamespace\SubNamespace\Something\D
5 | 3 | LongNamespace\SubNamespace\Something\B
6 | 6 | LongNamespace\SubNamespace\Something\C
... etc (around 50,000 rows) ...
每条记录添加 38 个字节,其中大部分是重复数据,我的问题是,在 relation_type
列上添加索引是否会将每个单独的 relation_type
记录分别存储在内存(我认为这就是索引所发生的情况),或者会将它们像 ENUM 一样分组,因此总存储将是 relation_type
中的 3 个唯一条目,然后它们通过某些哈希表在内部关联排序,因此节省了 n*38 字节的空间。
最佳答案
索引包含所有索引列的所有文本,加上(在 InnoDB 的情况下)所有 PRIMARY KEY
列的所有文本。因此,38*n 个字节被“浪费”了。
如果您将 relation_type
声明为
ENUM(`LongNamespace\SubNamespace\Something\B`,
`LongNamespace\SubNamespace\Something\C`,
`LongNamespace\SubNamespace\Something\D`,
...)
那么它只需要 1 或 2 个字节,但其行为与那些 39 字节字符串非常相似。
当然,当您添加另一个表等时,会存在维护问题。
另一方面,38*50K = ~2MB 是“小”,并不是什么大问题。
不,索引不保存在 RAM 中。然而,它是逐 block “缓存”在 RAM 中的。因此,如果索引(或表)非常大,由于数据未保留在缓存 (RAM) 中,将会产生额外的 I/O。但它仍然会“起作用”,尽管速度很慢。
关于MySQL varchar索引存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36196468/