英文:
Do columns with a unique-constraint need to be indexed?
问题
我正在使用Hibernate,在我的表中通过以下方式添加唯一约束到特定的列:uniqueConstraints = {@UniqueConstraint(columnNames = {"warehouseCode", "orderCode", "vendorId"})}
。我还需要在这些精确的列上添加一个索引。我的问题是,我是否需要明确地为这些列创建一个索引,还是唯一约束会自动为我创建索引?
英文:
I am using Hibernate to add unique-constraints over certain columns in my table as follows uniqueConstraints = {@UniqueConstraint(columnNames = {"warehouseCode", "orderCode", "vendorId"})},
. I need to add an index over these exact columns as well. My question is, do I need to explicitly create an index for these columns, or does the unique-constraint automatically do it for me?
答案1
得分: 3
从技术角度来看,唯一约束实际上并不保证一定会创建索引,但据我所知,没有任何数据库引擎不会创建索引。
需要注意的是,数据库引擎仍然完全可以对它们进行不同处理,许多数据库就是这样做的。然而,确实存在一种称为“唯一索引”的东西,你需要将其与唯一约束进行比较,以查看有意义的差异。唯一索引可以被禁用,从而会禁用唯一性检查(至少在大多数数据库引擎上是这样)。而唯一约束通常无法禁用。
在数据库领域,建议如果你实际上打算将其用作索引,则创建唯一索引;如果你只关心唯一性,则创建约束。正如我所说,在实际操作中,我所了解的每个数据库引擎都会通过创建索引来实现唯一约束,并且我所了解的每个数据库引擎都会在一般查询中使用该索引,因为它存在于那里。
这一切如何转化为 Hibernate?这就是 Hibernate 的问题所在——你只是增加了学习曲线,并没有简化任何事情,因为你通常需要了解在 SQL 方面发生了什么。
在这种情况下,翻译得不是很好,Hibernate 在这方面存在一些疏忽,似乎并不理解“唯一索引”这个概念。
编辑
再仔细考虑一下,这真的很荒谬——确实有很好的理由希望有一个索引,特别是要在 a asc、b desc、c asc
上建立索引,而这是无法通过例如 a asc、b asc、c asc
这样的方式伪造的。而且你还希望在 a/b/c 上实现唯一性。几乎每个数据库引擎都可以通过创建 a asc、b desc、c asc
的索引,并在创建时添加 UNIQUE 关键字来有效地实现这一点。
如果无法让 Hibernate 创建这样的内容,那么 Hibernate 似乎就不适合这个目的。
我试图找到关于如何创建它的文档,但我找不到。这太奇怪了。Hibernate 真的做不到这一点吗?
需要注意的是,像 JDBI 和 JOOQ 这样的工具存在,可以让你真正执行 SQL 操作。如果你已经熟悉数据库引擎和 SQL 等,并且在项目的早期阶段,你可能会想要了解如何在 Hibernate 中创建唯一索引,如果无法做到这一点,考虑是否切换。
编辑结束
因此,你有三个选择:
-
同时创建索引和唯一约束,使数据库进行双倍工作,减慢所有操作速度,并使事物的大小加倍。祈祷 Hibernate 足够智能,不会真正创建该索引,但我对其是否会这样工作表示怀疑。鉴于这是一个包含三个字段的索引,这是一个昂贵的操作,听起来并不是一个好主意。
-
保持不变,并依赖于所有数据库引擎将使用索引来实现此功能,并且将在查询中使用该索引,即使它不完全符合正确的“风格”,尤其是在直接连接到数据库时。
-
向 Hibernate 提交一个功能请求,或查找如何在 Hibernate 的
@Index
功能中将索引标记为“需要唯一性”。
英文:
Technically, a unique constraint does not actually guarantee that an index will be made, but I'm not aware of any DB engine that doesn't.
Note that a DB engine is nevertheless fully free to treat them differently, and many DBs do just that. However, there is such a thing as a unique index - and you'd need to compare one of those to a unique constraint to see meaningful differences. A unique index can be disabled, which in passing then disables the uniqueness checking (at least, on most DB engines). A unique constraint often cannot.
In DB land, the advice is to make a unique index if you actually intend to use it as an index, and to make a constraint if you just care about uniqueness. As I said, in practice, every DB engine I know implements a unique constraint by making an index, and every DB engine I know will use that index for general queries because it is there.
How does this all translate to hibernate? That's the problem with hibernate - you're just adding to the learning curve and simplify nothing, because often you need to know what's happening on the SQL side.
In this case, it translates quite badly, hibernate has a bit of an oversight and does not appear to understand that there is such a concept as a 'unique index'.
EDIT
Thinking about it some more, this really is nuts - there are good reasons to want an index, specifically. For example, let's say you want an index on a asc, b desc, c asc
, which cannot be faked in any way with e.g. a asc, b asc, c asc
. And you also want uniqueness over a/b/c in one go. Just about every DB engine can do this efficiently by way of making an index of a asc, b desc, c asc
, and adding the UNIQUE keyword as you make it.
If hibernate cannot be cajoled into making such a thing, that sure sounds like hibernate is not fit for purpose.
I'm trying to find docs on how to make it, but I just can't find it. It's bizarre. Can hibernate really not do this?
Note that tools like JDBI and JOOQ exists, which let you actually do SQL things. If you're already familiar with DB engines and SQL and the like, and you're early enough in this project, you may want to look for how to make a unique index in hibernate, and if you cannot, consider switching.
END EDIT
So, you have three choices:
-
Make both an index and the unique constraint, doubling the DBs work, slowing everything down, and doubling the size of things. Pray that hibernate is smart enough not to actually make that index, but I doubt that's how it would work. Given that it's a 3-field index, it's a pricey one, this does not sound like a good idea.
-
Leave it as is, and rely on the fact that all DB engines will be implementing this with an index and will use that index for queries as well, even though it's not quite the right 'style' especially when connecting straight to the DB.
-
File a feature request with hibernate or look up how you can flag an index as 'requires uniqueness' within hibernate's
@Index
functionality.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论