MySQL:创建没有索引的外键

Isr*_*eca 2 mysql sql indexing foreign-keys database-indexes

在MySQL 5.6.34中是否可以有没有索引的外键?我想要那是因为我在2000万行中用另一个表的外键创建了一个可为空的列。由于这是一项新功能,因此只有新行的该列可能会填充实际值,并且您可能会期望该索引的基数变得可怕。因此,在大多数情况下,使用该索引实际上不是一个好主意。问题:我有很多查询都具有相同的限制:

[...] from large_table where tenant_id = ? and nullable_foreign_key_with_index is null and [...]
Run Code Online (Sandbox Code Playgroud)

问题?MySQL认为使用index_merge / intersect策略进行查询解析是一个好主意。在这种情况下的MySQL会做2个查询并行:一个tenant_id(使用一个有效和良好的指数)和另一个nullable_foreign_key_with_index是坏的,几乎是给定的“全表并行扫描”,这个指数的基数是<1000中有超过2000万行的表格。有关此“问题”的更多详细信息,请参见此处

那么,什么是可行的解决方案?鉴于MySQL“强制”外键附加了索引:

  1. 删除外键和索引。这很糟糕,因为在应用程序出现错误的情况下,我们可能会损害参照完整性。

  2. FOREIGN_KEY_CHECKS = 0; 跌落指数;FOREIGN_KEY_CHECKS = 1。这很不好,因为即使外键仍然存在,MySQL也不再验证该列以检查该值是否实际存在。那是个错误吗?

  3. 在所有现有查询中使用查询提示,以确保我们仅使用旧的高效“ tenant_id_index”。这很糟糕,因为我必须查找所有现有查询,并且还记得在构建新闻查询时再次使用它。

因此,我怎么说:“ MySQL,不必为这个外键创建索引,而是继续验证相关​​表中的内容,该表无论如何都由主键索引”。我想念什么吗?到目前为止,最好的主意是删除外键,仅相信该应用程序可以按预期运行(可能确实如此),但这将引发关于在APP与DATABASE中具有约束的经典讨论。有任何想法吗?

Gor*_*off 5

对于此查询:

from large_table
where tenant_id = ? and
      nullable_foreign_key_with_index is null and [...]
Run Code Online (Sandbox Code Playgroud)

只需添加索引large_table(tenant_id, nullable_foreign_key_with_index)

MySQL应该在表中使用该索引。

我很确定您可以向后进行此操作(我将100%确定比较是否为以外的任何其他方法NULL,但我很确定MySQL NULL也会做正确的事情。)

large_table(nullable_foreign_key_with_index, tenant_id)
Run Code Online (Sandbox Code Playgroud)

MySQL将认识到该索引适用于外键,而不创建任何其他索引。