MySQL varchar索引存储

标签 mysql sql indexing enums

我有一个使用 Laravel 框架构建的应用程序。其功能之一是能够在表之间创建多态关系。它通过存储相关表的 ID 和相关表模型的完全限定类名来实现此目的。正如您可以想象的那样,某些条目可能会很长,具体取决于模型的命名空间和类名称。

在我的场景中,我有 4 个表。基表 A 是多态的。表 BCD 不是。

非多态表模型的类名称如下:

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/

相关文章:

mysql - 如何从多个表中加入 SELECT,其中 SELECTS 基于不同的条件?

php - 在 laravel 中测试调度器

sql - SELECT SQL,N 的倍数

mysql - 为什么 InnoDB 中索引大小大于数据大小?

mysql - 不知道为什么 django South 试图进行反向迁移

android - 如何使用 contextMenu 将值从 ListView 传递到项目的另一个 Activity

mysql - SQL查询价格检索

php - 如何获取并比较两个mysql数据?

android - Firestore "Invalid query"- 我使用索引错误吗?

string - Swift String 索引 advanceBy 不能采用 int32