我在add_index ~ unique: true
中看到schema.rb
声明,并认为唯一性是表的约束,而不是索引。使用索引是实现方式之一唯一性,程序员不应该指定RDBMS“如何”和索引加快搜索速度,但需要插入成本。事实上,还有另一种方法来保持唯一性约束吗?如果没有,为什么Rails只为我们提供add_index
唯一性约束声明?
答案 0 :(得分:2)
因为不需要其他方式。在引擎盖下,它们完全相同:当您定义UNIQUE
约束时,会在该表上创建UNIQUE
索引以强制执行它。
来自DBA.SE的问题:When should I use a unique constraint instead of a unique index?
因此,对于支持这两种功能的数据库,选择使用哪种功能通常会归结为首选样式和一致性。
因此在Rails中使用索引是一致的。这就是原因。
来自PostgreSQL's docs的引用:
当为表定义唯一约束或主键时,PostgreSQL会自动创建唯一索引。索引涵盖构成主键或唯一约束的列(如果适用,则为多列索引),并且是强制执行约束的机制。
我没有在权威来源中找到MySQL的相关引用,但“谣言随处可见”。
答案 1 :(得分:1)
保证唯一性约束的唯一安全方法是在数据库级别强制执行它。它没有任何问题,事实上,这是真正正确的方法。任何数据库设计者或管理员都会向您确认。
Rails提供了唯一性验证器,但它并不完全安全。实际上,它是基于对数据库的简单查询,但是执行选择和执行插入之间有一小段时间间隔使得它成为可能(并且很可能在高并发系统中或者如果插入需要合理的数量时间)因为这种竞争条件而创建了重复记录。
因此,保证唯一性的唯一方法是在数据库上使用唯一索引。如果您对此感到担心,您可能需要阅读一些数据库设计书籍或资源,以便从不同的角度重新评估问题。
您仍希望在模型中进行验证的原因是因为数据库(通常)不会尝试以用户友好的方式尝试解决冲突。模型中的验证将预先验证数据并防止DBMS引发异常。您可以检查验证结果并向用户显示友好消息。
仍然存在数据库约束,如果由于前面提到的竞争条件而导致验证通过,那么将引发异常的DBMS将确保您的数据完整性。